diff options
Diffstat (limited to 'test/test_cipher.rb')
-rw-r--r-- | test/test_cipher.rb | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/test/test_cipher.rb b/test/test_cipher.rb new file mode 100644 index 00000000..156fa2a9 --- /dev/null +++ b/test/test_cipher.rb @@ -0,0 +1,255 @@ +require_relative 'utils' + +if defined?(OpenSSL) + +class OpenSSL::TestCipher < Test::Unit::TestCase + + class << self + + def has_cipher?(name) + ciphers = OpenSSL::Cipher.ciphers + # redefine method so we can use the cached ciphers value from the closure + # and need not recompute the list each time + define_singleton_method :has_cipher? do |name| + ciphers.include?(name) + end + has_cipher?(name) + end + + def has_ciphers?(list) + list.all? { |name| has_cipher?(name) } + end + + end + + def setup + @c1 = OpenSSL::Cipher::Cipher.new("DES-EDE3-CBC") + @c2 = OpenSSL::Cipher::DES.new(:EDE3, "CBC") + @key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" + @iv = "\0\0\0\0\0\0\0\0" + @hexkey = "0000000000000000000000000000000000000000000000" + @hexiv = "0000000000000000" + @data = "DATA" + end + + def teardown + @c1 = @c2 = nil + end + + def test_crypt + @c1.encrypt.pkcs5_keyivgen(@key, @iv) + @c2.encrypt.pkcs5_keyivgen(@key, @iv) + s1 = @c1.update(@data) + @c1.final + s2 = @c2.update(@data) + @c2.final + assert_equal(s1, s2, "encrypt") + + @c1.decrypt.pkcs5_keyivgen(@key, @iv) + @c2.decrypt.pkcs5_keyivgen(@key, @iv) + assert_equal(@data, @c1.update(s1)+@c1.final, "decrypt") + assert_equal(@data, @c2.update(s2)+@c2.final, "decrypt") + end + + def test_info + assert_equal("DES-EDE3-CBC", @c1.name, "name") + assert_equal("DES-EDE3-CBC", @c2.name, "name") + assert_kind_of(Fixnum, @c1.key_len, "key_len") + assert_kind_of(Fixnum, @c1.iv_len, "iv_len") + end + + def test_dup + assert_equal(@c1.name, @c1.dup.name, "dup") + assert_equal(@c1.name, @c1.clone.name, "clone") + @c1.encrypt + @c1.key = @key + @c1.iv = @iv + tmpc = @c1.dup + s1 = @c1.update(@data) + @c1.final + s2 = tmpc.update(@data) + tmpc.final + assert_equal(s1, s2, "encrypt dup") + end + + def test_reset + @c1.encrypt + @c1.key = @key + @c1.iv = @iv + s1 = @c1.update(@data) + @c1.final + @c1.reset + s2 = @c1.update(@data) + @c1.final + assert_equal(s1, s2, "encrypt reset") + end + + def test_empty_data + @c1.encrypt + assert_raise(ArgumentError){ @c1.update("") } + end + + def test_initialize + assert_raise(RuntimeError) {@c1.__send__(:initialize, "DES-EDE3-CBC")} + assert_raise(RuntimeError) {OpenSSL::Cipher.allocate.final} + end + + def test_ctr_if_exists + begin + cipher = OpenSSL::Cipher.new('aes-128-ctr') + cipher.encrypt + cipher.pkcs5_keyivgen('password') + c = cipher.update('hello,world') + cipher.final + cipher.decrypt + cipher.pkcs5_keyivgen('password') + assert_equal('hello,world', cipher.update(c) + cipher.final) + end + end if has_cipher?('aes-128-ctr') + + if OpenSSL::OPENSSL_VERSION_NUMBER > 0x00907000 + def test_ciphers + OpenSSL::Cipher.ciphers.each{|name| + next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name + assert(OpenSSL::Cipher::Cipher.new(name).is_a?(OpenSSL::Cipher::Cipher)) + } + end + + def test_AES + pt = File.read(__FILE__) + %w(ECB CBC CFB OFB).each{|mode| + c1 = OpenSSL::Cipher::AES256.new(mode) + c1.encrypt + c1.pkcs5_keyivgen("passwd") + ct = c1.update(pt) + c1.final + + c2 = OpenSSL::Cipher::AES256.new(mode) + c2.decrypt + c2.pkcs5_keyivgen("passwd") + assert_equal(pt, c2.update(ct) + c2.final) + } + end + + def test_AES_crush + 500.times do + assert_nothing_raised("[Bug #2768]") do + # it caused OpenSSL SEGV by uninitialized key + OpenSSL::Cipher::AES128.new("ECB").update "." * 17 + end + end + end + end + + if has_ciphers?(['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm']) + + def test_authenticated + cipher = OpenSSL::Cipher.new('aes-128-gcm') + assert(cipher.authenticated?) + cipher = OpenSSL::Cipher.new('aes-128-cbc') + refute(cipher.authenticated?) + end + + def test_aes_gcm + ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'].each do |algo| + pt = "You should all use Authenticated Encryption!" + cipher, key, iv = new_encryptor(algo) + + cipher.auth_data = "aad" + ct = cipher.update(pt) + cipher.final + tag = cipher.auth_tag + assert_equal(16, tag.size) + + decipher = new_decryptor(algo, key, iv) + decipher.auth_tag = tag + decipher.auth_data = "aad" + + assert_equal(pt, decipher.update(ct) + decipher.final) + end + end + + def test_aes_gcm_short_tag + ['aes-128-gcm', 'aes-192-gcm', 'aes-256-gcm'].each do |algo| + pt = "You should all use Authenticated Encryption!" + cipher, key, iv = new_encryptor(algo) + + cipher.auth_data = "aad" + ct = cipher.update(pt) + cipher.final + tag = cipher.auth_tag(8) + assert_equal(8, tag.size) + + decipher = new_decryptor(algo, key, iv) + decipher.auth_tag = tag + decipher.auth_data = "aad" + + assert_equal(pt, decipher.update(ct) + decipher.final) + end + end + + def test_aes_gcm_wrong_tag + pt = "You should all use Authenticated Encryption!" + cipher, key, iv = new_encryptor('aes-128-gcm') + + cipher.auth_data = "aad" + ct = cipher.update(pt) + cipher.final + tag = cipher.auth_tag + + decipher = new_decryptor('aes-128-gcm', key, iv) + tag.setbyte(-1, (tag.getbyte(-1) + 1) & 0xff) + decipher.auth_tag = tag + decipher.auth_data = "aad" + + assert_raise OpenSSL::Cipher::CipherError do + decipher.update(ct) + decipher.final + end + end + + def test_aes_gcm_wrong_auth_data + pt = "You should all use Authenticated Encryption!" + cipher, key, iv = new_encryptor('aes-128-gcm') + + cipher.auth_data = "aad" + ct = cipher.update(pt) + cipher.final + tag = cipher.auth_tag + + decipher = new_decryptor('aes-128-gcm', key, iv) + decipher.auth_tag = tag + decipher.auth_data = "daa" + + assert_raise OpenSSL::Cipher::CipherError do + decipher.update(ct) + decipher.final + end + end + + def test_aes_gcm_wrong_ciphertext + pt = "You should all use Authenticated Encryption!" + cipher, key, iv = new_encryptor('aes-128-gcm') + + cipher.auth_data = "aad" + ct = cipher.update(pt) + cipher.final + tag = cipher.auth_tag + + decipher = new_decryptor('aes-128-gcm', key, iv) + decipher.auth_tag = tag + decipher.auth_data = "aad" + + assert_raise OpenSSL::Cipher::CipherError do + decipher.update(ct[0..-2] << ct[-1].succ) + decipher.final + end + end + + end + + private + + def new_encryptor(algo) + cipher = OpenSSL::Cipher.new(algo) + cipher.encrypt + key = cipher.random_key + iv = cipher.random_iv + [cipher, key, iv] + end + + def new_decryptor(algo, key, iv) + OpenSSL::Cipher.new(algo).tap do |cipher| + cipher.decrypt + cipher.key = key + cipher.iv = iv + end + end + +end + +end |