Viblo Code
+1

Ruby AES Encryption using OpenSSL

Ruby AES Encryption

Trong mật mã học ta đã biết có hai thuật toán mã hóa được sử dụng đó là: mã hóa đối xứng (Symmetric Encryption Algorithms) và mã hóa bất đối xứng (Asymmetric Encryption Algorithms).

Symmmetric Encryption Algorithms: thuật toán này sử dụng một chìa khóa duy nhất (nó được gọi là private key hoặc secret key) để mã hóa và giải mã dữ liệu.

Asymmetric Encryption Algorithms: thuật toán này sử dụng một cặp key khác nhau cho việc mã hóa và giải mã. Key dùng cho việc mã hóa được hóa gọi là public key, còn một key dùng cho việc giải mã được gọi là private key.

Mã hóa AES: là một trong các thuật toán Symmetric key phổ biến. Nó là viết tắt của của cụm từ "Advanced Encryption Standard".

Hơn nữa AES còn là một thuật toán mã hóa khối (Block cipher) một kiểu thuật toán mã hóa một nhóm nhiều bit. Nó sử dụng Sym key với 3 phiên bản block cipher khác nhau: AES-128, AES-192 và AES-256. Trên thực tế, các block cipher đều là 128-bit nhưng độ dài key của chúng lần lượt là 128-bit, 192-bit và 256-bit.

Ưu điểm của AES: đó là tốc độ nhanh do nó thiết kế chỉ một key duy nhất trong qúa trình mã hóa và giải mã dữ liệu. tiếp nữa là đảm bảo tính tối mật dữ liệu (confidentiality) nghĩa là thông tin chỉ được tiết lộ cho những ai được phép.

Hạn chế của AES: đó là private key phải được lưu trữ đảm bảo an toàn không bị mất. Trong qúa trình truyền thông tin của key giữa các máy tính phải đảm bảo việc truyền dữ liệu về key( tức là bảo mật qúa trình truyền key trên mạng)

Sơ đồ AES Encryption: Screenshot from 2015-10-27 00:57:21.png

Chú thích:

Plaintext (cleartext): dữ liệu gốc (chưa được mã hóa). Ciphertext: dữ liệu đã được mã hóa.

Mã hóa và giải mã được thực hiện tương đối dễ dàng nhờ sự trợ giúp của thư viện OpenSSL được cung cấp cho Ruby.

OpenSSL

Đầu tiên ta hiểu là OpenSSL là một tiện ích nguồn mở dùng để mã hoá dữ liệu. là một thư viện rất quan trọng trong nghành công nghệ bảo mật.

Cung cấp cho ta rất nhiều các module hữu ích sử dụng để mã hóa (Encrypt) và giải mã (Decrypt).

Trong Ruby có một module rất hữu ích được cung cấp mặc định đó là module Cipher của thư viện openssl.

Trong bài viết này sẽ hướng dẫn sử dụng module Cipher trong việc mã hóa và giải mã .

Các bước thực hiện:

Encryption:

cipher = OpenSSL::Cipher.new 'AES-128-CBC'
#Khởi tạo đối tượng Cipher với đối số truyền vào là
    name: thuật toán AES,
    key-length: 128-bit,
    mode: CBC

cipher.encrypt
#Encryption

iv = cipher.random_iv
#initialization vector

pwd = 'password for encryption'

salt = OpenSSL::Random.random_bytes 16
#chuỗi salt được append vào password trước khi hash

iter = 20000
#thời gian sinh key

key_len = cipher.key_len
#độ dài khóa được sinh ra(128-bit)--phải tương thích với thuật toán mã hóa AES

digest = OpenSSL::Digest::SHA256.new
#Signatures

key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
#Ở đây dùng module PKCS5 để sinh key từ một pasword cho trước (pwd)

cipher.key = key

Giờ ta có thể thử nó trên terminal để xem kết quả:

2.2.3 :001 > require 'openssl'
 => true
2.2.3 :002 > cipher = OpenSSL::Cipher.new 'AES-128-CBC'
 => #<OpenSSL::Cipher:0xb8c618a4>
2.2.3 :003 > cipher.encrypt
 => #<OpenSSL::Cipher:0xb8c618a4>
2.2.3 :004 > iv = cipher.random_iv
 => "\xD0wj\xB7\xBF\xD1\x11\x82 \xFE\x1A\xB6\xFBAC?"
2.2.3 :005 > pwd = 'password for encryption'
 => "password for encryption"
2.2.3 :006 > salt = OpenSSL::Random.random_bytes 16
 => "A\xC5\xEF\xF2\x15\xD7-\x9D\x7F%\xB0|\xB6\b{\x1D"
2.2.3 :007 > iter = 20000
 => 20000
2.2.3 :008 > key_len = cipher.key_len
 => 16
2.2.3 :009 > digest = OpenSSL::Digest::SHA256.new
 => #<OpenSSL::Digest::SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855>
2.2.3 :010 > key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
 => "z\x80\x05\x16\xA2\x17hVp/\xB6\x8E\xDAJ\xA7\xF6"
2.2.3 :011 >  cipher.key = key
 => "z\x80\x05\x16\xA2\x17hVp/\xB6\x8E\xDAJ\xA7\xF6"

2.2.3 :012 > encrypted = cipher.update 'i love u'
 => ""
2.2.3 :013 > encrypted << cipher.final
 => "\x9D\x12:-\xD0l\x84q\xCB\xCD\xF6\x8B;\x8D5\v"

kết quả: plaintext 'i love u' ---> được mã hóa thành "\x9D\x12:-\xD0l\x84q\xCB\xCD\xF6\x8B;\x8D5\v"

Decryption:

cipher = OpenSSL::Cipher.new 'AES-128-CBC'
cipher.decrypt
cipher.iv = iv
pwd = 'sassword for encryption'
salt = salt
iter = 20000
key_len = cipher.key_len
digest = OpenSSL::Digest::SHA256.new
key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
cipher.key = key

Bây giờ ta sẽ kiểm tra kết quả quá trình giải mã:

2.2.3 :014 > cipher = OpenSSL::Cipher.new 'AES-128-CBC'
 => #<OpenSSL::Cipher:0xb8c350b0>
2.2.3 :015 > cipher.decrypt
 => #<OpenSSL::Cipher:0xb8c350b0>
2.2.3 :016 > cipher.iv = iv
 => "\xD0wj\xB7\xBF\xD1\x11\x82 \xFE\x1A\xB6\xFBAC?"
2.2.3 :017 > pwd = 'password for encryption'
 => "password for encryption"
2.2.3 :018 > salt = salt
 => "A\xC5\xEF\xF2\x15\xD7-\x9D\x7F%\xB0|\xB6\b{\x1D"
2.2.3 :019 > iter = 20000
 => 20000
2.2.3 :020 > key_len = cipher.key_len
 => 16
2.2.3 :021 > digest = OpenSSL::Digest::SHA256.new
 => #<OpenSSL::Digest::SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855>
2.2.3 :022 > key = OpenSSL::PKCS5.pbkdf2_hmac(pwd, salt, iter, key_len, digest)
 => "z\x80\x05\x16\xA2\x17hVp/\xB6\x8E\xDAJ\xA7\xF6"
2.2.3 :023 > cipher.key = key
 => "z\x80\x05\x16\xA2\x17hVp/\xB6\x8E\xDAJ\xA7\xF6"

2.2.3 :024 > decrypted = cipher.update encrypted
 => ""
2.2.3 :025 > decrypted << cipher.final
 => "i love u"

OK!!!

Có thể tìm hiểu rõ hơn ở các trang sau:

http://docs.ruby-lang.org/en/trunk/OpenSSL/Cipher.html http://ruby-doc.org/stdlib-2.2.3/libdoc/openssl/rdoc/OpenSSL/PKCS5.html http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL.html


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.