diff --git a/src/lua/crypto.lua b/src/lua/crypto.lua
index d63f5a0151fd6594a1355e24cebbb332b28d5a40..bd9019c8a186f35fd07b587b8b19312067c4a163 100644
--- a/src/lua/crypto.lua
+++ b/src/lua/crypto.lua
@@ -4,6 +4,12 @@ local ffi = require 'ffi'
 local buffer = require('buffer')
 
 ffi.cdef[[
+    /* from openssl/err.h */
+    unsigned long ERR_get_error(void);
+    char *ERR_error_string(unsigned long e, char *buf);
+    void ERR_load_ERR_strings(void);
+    void ERR_load_crypto_strings(void);
+
     /* from openssl/evp.h */
     void OpenSSL_add_all_digests();
     void OpenSSL_add_all_ciphers();
@@ -50,11 +56,16 @@ if ssl == nil then
         if ssl ~= nil then
             ssl.OpenSSL_add_all_digests()
             ssl.OpenSSL_add_all_ciphers()
+            ssl.ERR_load_crypto_strings()
             break
         end
     end
 end
 
+local function openssl_err_str()
+  return ffi.string(ssl.ERR_error_string(ssl.ERR_get_error(), nil))
+end
+
 local digests = {}
 if ssl then
   for class, name in pairs({
@@ -62,7 +73,10 @@ if ssl then
       sha = 'SHA', sha1 = 'SHA1', sha224 = 'SHA224',
       sha256 = 'SHA256', sha384 = 'SHA384', sha512 = 'SHA512',
       dss = 'DSS', dss1 = 'DSS1', mdc2 = 'MDC2', ripemd160 = 'RIPEMD160'}) do
-      digests[class] = ssl.EVP_get_digestbyname(class)
+      local digest = ssl.EVP_get_digestbyname(class)
+      if digest ~= nil then
+          digests[class] = digest
+      end
   end
 end
 
@@ -75,7 +89,7 @@ end
 local function digest_new(digest)
     local ctx = ssl.EVP_MD_CTX_create()
     if ctx == nil then
-        return error('Can\'t create digest ctx')
+        return error('Can\'t create digest ctx: ' .. openssl_err_str())
     end
     ffi.gc(ctx, digest_gc)
     local self = setmetatable({
@@ -94,7 +108,7 @@ local function digest_init(self)
         return error('Digest context isn\'t usable')
     end
     if ssl.EVP_DigestInit_ex(self.ctx, self.digest, nil) ~= 1 then
-        return error('Can\'t init digest')
+        return error('Can\'t init digest: ' .. openssl_err_str())
     end
     self.initialized = true
 end
@@ -104,7 +118,7 @@ local function digest_update(self, input)
         return error('Digest not initialized')
     end
     if ssl.EVP_DigestUpdate(self.ctx, input, input:len()) ~= 1 then
-        return error('Can\'t update digest')
+        return error('Can\'t update digest: ' .. openssl_err_str())
     end
 end
 
@@ -114,7 +128,7 @@ local function digest_final(self)
     end
     self.initialized = false
     if ssl.EVP_DigestFinal_ex(self.ctx, self.buf.wpos, self.outl) ~= 1 then
-        return error('Can\'t finalize digest')
+        return error('Can\'t finalize digest: ' .. openssl_err_str())
     end
     return ffi.string(self.buf.wpos, self.outl[0])
 end
@@ -142,8 +156,11 @@ if ssl then
       local algo_api = {}
       for mode, mode_name in pairs({cfb = 'CFB', ofb = 'OFB',
           cbc = 'CBC', ecb = 'ECB'}) do
-              algo_api[mode] =
+              local cipher =
                   ssl.EVP_get_cipherbyname(algo_name .. '-' .. mode_name)
+              if cipher ~= nil then
+                  algo_api[mode] = cipher
+              end
       end
       if algo_api ~= {} then
           ciphers[algo] = algo_api
@@ -158,15 +175,24 @@ local function cipher_gc(ctx)
 end
 
 local function cipher_new(cipher, key, iv, direction)
+    local block_size = ssl.EVP_CIPHER_block_size(cipher)
+    if key == nil or key:len() < block_size then
+      return error('Key length should be equal cipher block size ('
+        .. tostring(block_size) .. ')')
+    end
+    if iv == nil or iv:len() < block_size then
+      return error('Initial vector length should be equal cipher block size ('
+        .. tostring(block_size) .. ')')
+    end
     local ctx = ssl.EVP_CIPHER_CTX_new()
     if ctx == nil then
-        return error('Can\'t create cipher ctx')
+        return error('Can\'t create cipher ctx: ' .. openssl_err_str())
     end
     ffi.gc(ctx, cipher_gc)
     local self = setmetatable({
         ctx = ctx,
         cipher = cipher,
-        block_size = ssl.EVP_CIPHER_block_size(cipher),
+        block_size = block_size,
         direction = direction,
         buf = buffer.ibuf(),
         initialized = false,
@@ -180,9 +206,9 @@ local function cipher_init(self, key, iv)
     if self.ctx == nil then
         return error('Cipher context isn\'t usable')
     end
-    if ssl.EVP_CipherInit_ex(self.ctx, self.cipher, nil, 
+    if ssl.EVP_CipherInit_ex(self.ctx, self.cipher, nil,
         key, iv, self.direction) ~= 1 then
-        return error('Can\'t init cipher')
+        return error('Can\'t init cipher:' .. openssl_err_str())
     end
     self.initialized = true
 end
@@ -191,9 +217,13 @@ local function cipher_update(self, input)
     if not self.initialized then
         return error('Cipher not initialized')
     end
+    if input == nil then
+      return ''
+    end
+    input = tostring(input)
     local wpos = self.buf:reserve(input:len() + self.block_size - 1)
     if ssl.EVP_CipherUpdate(self.ctx, wpos, self.outl, input, input:len()) ~= 1 then
-        return error('Can\'t update cipher')
+        return error('Can\'t update cipher:' .. openssl_err_str())
     end
     return ffi.string(wpos, self.outl[0])
 end
@@ -205,7 +235,7 @@ local function cipher_final(self)
     self.initialized = false
     local wpos = self.buf:reserve(self.block_size - 1)
     if ssl.EVP_CipherFinal_ex(self.ctx, wpos, self.outl) ~= 1 then
-        return error('Can\'t finalize cipher')
+        return error('Can\'t finalize cipher:' .. openssl_err_str())
     end
     self.initialized = false
     return ffi.string(wpos, self.outl[0])
@@ -254,7 +284,7 @@ digest_api = setmetatable(digest_api,
     ' is not supported or SSL library not found') end })
 
 local function cipher_mode_error(self, mode)
-  error('Cipher mode' .. mode .. ' is not supported')
+  error('Cipher mode ' .. mode .. ' is not supported')
 end
 
 local cipher_api = {}
diff --git a/test/app/crypto.result b/test/app/crypto.result
new file mode 100644
index 0000000000000000000000000000000000000000..085c0803548ef5b2d310ec336ffdd07fbf982bc9
--- /dev/null
+++ b/test/app/crypto.result
@@ -0,0 +1,110 @@
+crypto = require('crypto')
+---
+...
+type(crypto)
+---
+- table
+...
+ciph = crypto.cipher.aes128.cbc
+---
+...
+pass = '12345678876543211234567887654321'
+---
+...
+iv = 'abcdefghijklmnopqrstuvwxyz123456'
+---
+...
+enc = ciph.encrypt('test', pass, iv)
+---
+...
+enc
+---
+- !!binary WpJJu6l6oziZcyvND8KueA==
+...
+ciph.decrypt(enc, pass, iv)
+---
+- test
+...
+--Failing scenaries
+crypto.cipher.aes128.cbc.encrypt('a')
+---
+- error: 'builtin/crypto.lua:302: Key length should be equal cipher block size (16)'
+...
+crypto.cipher.aes128.cbc.encrypt('a', '123456', '435')
+---
+- error: 'builtin/crypto.lua:302: Key length should be equal cipher block size (16)'
+...
+crypto.cipher.aes128.cbc.encrypt('a', '1234567887654321')
+---
+- error: 'builtin/crypto.lua:302: Initial vector length should be equal cipher block
+    size (16)'
+...
+crypto.cipher.aes128.cbc.encrypt('a', '1234567887654321', '12')
+---
+- error: 'builtin/crypto.lua:302: Initial vector length should be equal cipher block
+    size (16)'
+...
+crypto.cipher.aes256.cbc.decrypt('a')
+---
+- error: 'builtin/crypto.lua:302: Key length should be equal cipher block size (16)'
+...
+crypto.cipher.aes256.cbc.decrypt('a', '123456', '435')
+---
+- error: 'builtin/crypto.lua:302: Key length should be equal cipher block size (16)'
+...
+crypto.cipher.aes256.cbc.decrypt('a', '12345678876543211234567887654321')
+---
+- error: 'builtin/crypto.lua:302: Initial vector length should be equal cipher block
+    size (16)'
+...
+crypto.cipher.aes256.cbc.decrypt('12', '12345678876543211234567887654321', '12')
+---
+- error: 'builtin/crypto.lua:302: Initial vector length should be equal cipher block
+    size (16)'
+...
+crypto.cipher.aes192.cbc.encrypt.new()
+---
+- error: Key length should be equal cipher block size (16)
+...
+crypto.cipher.aes192.cbc.encrypt.new('123321')
+---
+- error: Key length should be equal cipher block size (16)
+...
+crypto.cipher.aes192.cbc.decrypt.new('123456788765432112345678')
+---
+- error: Initial vector length should be equal cipher block size (16)
+...
+crypto.cipher.aes192.cbc.decrypt.new('123456788765432112345678', '12345')
+---
+- error: Initial vector length should be equal cipher block size (16)
+...
+crypto.cipher.aes100.efb
+---
+- error: 'builtin/crypto.lua:318: Cipher method aes100 is not supported or SSL library
+    not found'
+...
+crypto.cipher.aes256.nomode
+---
+- error: 'builtin/crypto.lua:287: Cipher mode nomode is not supported'
+...
+crypto.digest.nodigest
+---
+- error: 'builtin/crypto.lua:283: Digest method nodigest is not supported or SSL library
+    not found'
+...
+bad_pass = '87654321123456788765432112345678'
+---
+...
+bad_iv = '123456abcdefghijklmnopqrstuvwxyz'
+---
+...
+ciph.decrypt(enc, bad_pass, iv)
+---
+- error: 'builtin/crypto.lua:304: Can''t finalize cipher:error:06065064:digital envelope
+    routines:EVP_DecryptFinal_ex:bad decrypt'
+...
+ciph.decrypt(enc, pass, bad_iv)
+---
+- error: 'builtin/crypto.lua:304: Can''t finalize cipher:error:06065064:digital envelope
+    routines:EVP_DecryptFinal_ex:bad decrypt'
+...
diff --git a/test/app/crypto.test.lua b/test/app/crypto.test.lua
new file mode 100644
index 0000000000000000000000000000000000000000..b42c63be957380ac3bda0899b9ca7871933fcbbe
--- /dev/null
+++ b/test/app/crypto.test.lua
@@ -0,0 +1,38 @@
+crypto = require('crypto')
+type(crypto)
+
+ciph = crypto.cipher.aes128.cbc
+pass = '12345678876543211234567887654321'
+iv = 'abcdefghijklmnopqrstuvwxyz123456'
+enc = ciph.encrypt('test', pass, iv)
+enc
+ciph.decrypt(enc, pass, iv)
+
+
+--Failing scenaries
+crypto.cipher.aes128.cbc.encrypt('a')
+crypto.cipher.aes128.cbc.encrypt('a', '123456', '435')
+crypto.cipher.aes128.cbc.encrypt('a', '1234567887654321')
+crypto.cipher.aes128.cbc.encrypt('a', '1234567887654321', '12')
+
+crypto.cipher.aes256.cbc.decrypt('a')
+crypto.cipher.aes256.cbc.decrypt('a', '123456', '435')
+crypto.cipher.aes256.cbc.decrypt('a', '12345678876543211234567887654321')
+crypto.cipher.aes256.cbc.decrypt('12', '12345678876543211234567887654321', '12')
+
+crypto.cipher.aes192.cbc.encrypt.new()
+crypto.cipher.aes192.cbc.encrypt.new('123321')
+crypto.cipher.aes192.cbc.decrypt.new('123456788765432112345678')
+crypto.cipher.aes192.cbc.decrypt.new('123456788765432112345678', '12345')
+
+crypto.cipher.aes100.efb
+crypto.cipher.aes256.nomode
+
+crypto.digest.nodigest
+
+
+bad_pass = '87654321123456788765432112345678'
+bad_iv = '123456abcdefghijklmnopqrstuvwxyz'
+ciph.decrypt(enc, bad_pass, iv)
+ciph.decrypt(enc, pass, bad_iv)
+
diff --git a/test/app/digest.result b/test/app/digest.result
index 0ed6bcdbd18633bc9561c9a4bcddeaf54cdd5b69..ad6f88666368a55179cabfa2249399ddf688e321 100644
--- a/test/app/digest.result
+++ b/test/app/digest.result
@@ -326,7 +326,8 @@ digest.aes256cbc.decrypt(digest.aes256cbc.encrypt('test123', 'passpasspasspasspa
 ...
 digest.aes256cbc.decrypt(digest.aes256cbc.encrypt('test123', 'passpasspasspasspasspasspasspass', 'iv12tras8712cvbhuytrghjklmnbdr34'), 'nosspasspasspasspasspasspasspass', 'iv12tras8712cvbhuytrghjklmnbdr34')
 ---
-- error: 'builtin/crypto.lua:274: Can''t finalize cipher'
+- error: 'builtin/crypto.lua:304: Can''t finalize cipher:error:06065064:digital envelope
+    routines:EVP_DecryptFinal_ex:bad decrypt'
 ...
 digest = nil
 ---