пятница, 7 ноября 2014 г.

clojure: how to send mail with attachment

It is pretty simple. This code can be used to send email via smtp. Attachment filename may be in unicode.


(defproject com.middlesphere/mailer "0.1"
  :description "simple mailer"
  :url "http://www.middlesphere.com"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.6.0"]
                 [com.draines/postal "1.11.2"]
                 [com.sun.mail/javax.mail "1.5.2"]]
  :main ^:skip-aot mailer.core
  :target-path "target/%s"
  :omit-source true
  :profiles {:uberjar {:aot :all}})


(ns mailer.core
  (:require [clojure.edn :as edn])
  (:use [postal.core])
  (:import (javax.mail.internet MimeUtility)))

(defn show-help-exit
  (println "Usage: java -jar mailer.jar \"config-file\" \"email@email\" \"subject\" \"filename-with-body\" \"filename-with-attach\"\n ")
  (System/exit 0))

(defn -main
  "entry point to program."
  [& args]
  (println "start" (-> (java.text.SimpleDateFormat. "YYYY-mm-dd HH:mm:ss")
                       (.format (java.util.Date.))))

  (when (= "-h" (nth args 0))
  (when (not= 5 (count args))
    (println "error: wrong number of arguments!")

    (let [[config-file email-to subject body-file attach-file] args
          config (edn/read-string (slurp config-file))
          server-cfg {:host (config :host)
                      :port (config :port)}
          server-cfg (if (config :need-auth?)
                       (assoc server-cfg :user (config :user) :pass (config :pass))
          server-cfg (if (config :use-ssl?)
                       (assoc server-cfg :ssl true)
          server-cfg (if (config :use-tls?)
                       (assoc server-cfg :tls true)
      (println (format "config in:%s\nemail: %s\nsubject: %s\nbody in: %s\nattach in: %s\n" config-file email-to subject body-file attach-file))
      (println (send-message server-cfg                            
                             {:from (config :from)
                              :to email-to
                              :subject subject
                              :body [:alternative
                                     {:type (config :body-type)
                                      :content (slurp body-file)}
                                     {:type :attachment
                                      :content (java.io.File. attach-file)
                                      :file-name (MimeUtility/encodeText attach-file)
                                      :content-type (config :content-type)}]})))
    (catch Exception e (str "caught exception: " (.getMessage e))))
  (println "\nend" (-> (java.text.SimpleDateFormat. "YYYY-mm-dd HH:mm:ss")
                       (.format (java.util.Date.)))))


{:from "from@gmail.com"
 :host "smtp.gmail.com"
 :port 465
 :use-ssl? true
 :use-tls? false

 :need-auth? true
 :user "MyLogin"
 :pass "dis is passwd"

 :body-type "text/plain; charset=utf-8"
 :content-type "application/octet-stream"}

Test run

java -jar mailer-0.1-standalone.jar mailer-config.edn "to@gmail.com" "test-subject" "file-with-body.txt" "file-to-be-attached.doc"

вторник, 26 августа 2014 г.

scan hbase with specific row

source: http://stackoverflow.com/questions/16849641/row-keys-through-the-hbase-shell

so if you want to find some row with specific word in it then
hbase(main):003:0> import org.apache.hadoop.hbase.filter.CompareFilter
hbase(main):005:0> import org.apache.hadoop.hbase.filter.SubstringComparator
hbase(main):006:0> scan 'test', {FILTER => org.apache.hadoop.hbase.filter.RowFilter.new(CompareFilter::CompareOp.valueOf('EQUAL'),SubstringComparator.new("word_by_which_you_want_to_search"))}

Also, http://stackoverflow.com/questions/11068418/get-filtered-rows-in-hbase
import org.apache.hadoop.hbase.filter.CompareFilter
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter
import org.apache.hadoop.hbase.filter.SubstringComparator
import org.apache.hadoop.hbase.util.Bytes

scan 'yourTable', {LIMIT => 10, FILTER => SingleColumnValueFilter.new(Bytes.toBytes('family'), Bytes.toBytes('field'), CompareFilter::CompareOp.valueOf('EQUAL'), Bytes.toBytes('AAA')), COLUMNS => 'family:field' }

вторник, 22 июля 2014 г.

cron java and utf-8

If you ever run java application from cron job you might notice that any unicode characters that java application emits looks like ????????

In order to avoid this situation in RHEL-based distros you need to create /etc/environment file and then put here a value of LANG variable. For example: LANG=ru_RU.UTF-8  (without word export or something else)  

воскресенье, 6 июля 2014 г.

Solving random numbers problem

This library https://bitbucket.org/mike1452/msprandom demonstrates a technique which allows to solve the problem of getting random numbers on computers and small devices for cryptographic purposes. So, if you need encrypt and sign data on a small device or computer without hardware RNG do the following:
  1. Create true random numbers vault using this library on your computer or notebook.
  2. Put this vault on your device, computer or server where you need encrypt and sign data.
  3. Load the vault once at the start of the program when you need encrypt or sign data.
  4. Call secure-rand function to get random bytes as many times as you need.
Vault is encrypted and secured with HMAC. Random data in a vault is updated every time you load random seed with unpredictable way, so HMAC is recalculated too.

Gathering a true random data

To get a true random data a human input is used. Algorithm of collecting a random data:
  1. Run separate thread where atomic counter increments every tic from 0..255 with a very high speed.
  2. Wait for unbuffered key press by human and get a scan code of pressed button.
  3. Take current nanoseconds value from start of Epoch and take mod 256 to convert its value to a random byte.
  4. Xor values between each other: scan-code-byte ^ current-counter-value ^ nanoseconds to produce random byte.
  5. Add random byte to output vector. We suppose that only 3 bits has true randomness in this random byte. So, to get true random 32 bytes we need ~ 32*3 button press from user input. 6 Repeat steps 2-5 until we get required amount of random bytes.
  6. If we collected required amount of random data then do final step -> hash output vector with cryptographically strong hash function GOST 3411-94 to guarantee that probability 1 and 0 bits in output vector will be 0.5. Note, that hash function used here only to mix random bits and do not influence to the quality of random data. So hash(random data) = random data. Hash will produce vector of 32 bytes containing a random data.
  7. Repeat steps 1..7 if we need more than 32 bytes of random data.
Using this algorithm we collect a true 512 random bits. Why 512? Well, every PRNG needs a true random seed. If an attacker knows a seed then you can't protect your data. 256 bit length is far enough to keep millitary grade secrets. I did 512 to close the security question of random seed. My opinion, 512 bit of true random data is enough to use in PRNG: generating keys, signatures, etc.

четверг, 12 июня 2014 г.

call clojure code from java

Since clojure 1.6 there is no more special dances inside clojure code: special declarations or wrappers or something else. it is possible call clojure code from jar file like this. Clojure code (jar file) and clojure-1.6.jar should be in a class-path.

import clojure.java.api.Clojure;
import clojure.lang.IFn;

        IFn require = Clojure.var("clojure.core", "require");

        IFn myf0 = Clojure.var("my-clj-project.core", "my-clojure-func0");

or  myf0.invoke(param1, param2);

среда, 11 июня 2014 г.

How to break JCE crypto policy limit when using bouncycastle

    //this code allows to break limit if client jdk/jre has no unlimited policy files for JCE.
    //it should be run once. So this static section is always execute during the class loading process.
//this code is useful when working with Bouncycastle library.
    static {
        try {
            Field field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
            field.set(null, java.lang.Boolean.FALSE);
        } catch (Exception ex) {

or clojure variant of this function

(defn break-jce-policy-limit
  "This function breaks JCE crypto limits. Should be run once, primarily at the begining of the program
  to avoid JCE policy limit if JDK/JRE runtime has no installed files for break crypto limit. Returns nil."
  (safe (let [field (-> (Class/forName "javax.crypto.JceSecurity")
                      (.getDeclaredField "isRestricted"))]
          (.setAccessible field true)
          (.set field nil java.lang.Boolean/FALSE))))

(defmacro safe [bindings? & forms]
  "This macro is used to execute any function inside try-catch block."
  (let [bindings (if (and (even? (count bindings?)) (vector? bindings?))
                   bindings? nil)
        forms (if bindings forms (cons bindings? forms))
        except `(catch Exception e# e#
                  (println (.getMessage e#) e#))]
    (if bindings
      `(let ~bindings (try ~@forms ~except))
      `(try ~@forms ~except))))