Code Monkey home page Code Monkey logo

encryptor's People

Contributors

borama avatar rcook avatar saghaulor avatar shuber avatar tamird avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

encryptor's Issues

How to stop encrypting a column

I have a column using attr_encrypted that I now need to store in plaintext and stop encrypting. What's the best way to do this in a migration? I'm using version 1.3.2.

I suggest adding the answer to the documentation.

Setting a new cipher algorithm is not overriding the default algorithm

When running through the basic example on a windows machine and setting the cipher to use aes-256-cbc

cipher = OpenSSL::Cipher.new('aes-256-cbc')
cipher.encrypt # Required before '#random_key' or '#random_iv' can be called. http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-i-encrypt
secret_key = cipher.random_key # Insures that the key is the correct length respective to the algorithm used.
iv = cipher.random_iv # Insures that the IV is the correct length respective to the algorithm used.
salt = SecureRandom.random_bytes(16)
encrypted_value = Encryptor.encrypt(value: 'some string to encrypt', key: secret_key, iv: iv, salt: salt)
decrypted_value = Encryptor.decrypt(value: encrypted_value, key: secret_key, iv: iv, salt: salt)

It errors out at with the following:

[10] pry(main)> encrypted_value=Encryptor.encrypt(value: 'some string to encrypt', key: secret_key, iv: iv, salt: salt)
RuntimeError: unsupported cipher algorithm (aes-256-gcm)
from C:/RailsInstaller/Ruby2.1.0/lib/ruby/gems/2.1.0/gems/encryptor-3.0.0/lib/encryptor.rb:57:in initialize'

It appears that setting a new cipher algorithm is not overriding the default algorithm.

ArgumentError: key must be 32 bytes

I'm using encryptor via attr-encrypted in a Rails 5 application. While evaluating an upgrade to Ruby 2.4.0, I came across the following error coming out of this gem. Not sure if this is a bug, or something I'm doing wrong, or some change related to Ruby 2.4.0 that requires some effort on my part.

From Ruby 2.4.0

[7] pry(main)> RUBY_VERSION
=> "2.4.0"
[8] pry(main)> secret_key = SecureRandom.random_bytes(64)
=> "\xF3\xA6\xE9\x91\xFD\x94\xCB\xBDH\xA9|\xDF\x04\xBF\xAC\x13+0\xB5\xAF`[\b\xE6\xEDw\xCDD\x97\x19\"\xD1\xB1\xFB\x8A\x8Cn\x84N\x05\xDCp\x1C\xA0o3\x9D\t\xFA\x1F\xC1\x1C&F\xFC\xB0,\xDB\xBE\xE1\x8E9\xD4\xA6"
[9] pry(main)> iv = SecureRandom.random_bytes(12)
=> "\xD5\x00\xB1Q.>)\xAE\xF0x\xBB\xA1"
[10] pry(main)> encrypted_value = Encryptor.encrypt(value: 'some string to encrypt', key: secret_key, iv: iv)
ArgumentError: key must be 32 bytes
from /home/darren/.gem/ruby/2.4.0/gems/encryptor-3.0.0/lib/encryptor.rb:72:in `key='

Previous behavior from Ruby 2.3.3

[1] pry(main)> RUBY_VERSION
=> "2.3.3"
[2] pry(main)> secret_key = SecureRandom.random_bytes(64)
=> "A\xFD\xBC\xA5\x1A\x8E\xD7\x17W\x00r5\x8CHv|\xA7\xFB6\xB8N\x9Fb\x93\xA4\x9Aw\x8E\bq\xBA\xFC\xEF\xA3\x9E\xE2\xED\xB1\b\xBC\xE3\xDA\xEA\xDB\xF2\xAC0\xDAh\xCE\x88/(\x16\xC9\xDDs9\xD11\xE5\xE9\t\\"
[3] pry(main)> iv = SecureRandom.random_bytes(12)
=> "\xC8\xE3\xBE\x91y\x95sF\xE6\x89\x8C\""
[4] pry(main)> encrypted_value = Encryptor.encrypt(value: 'some string to encrypt', key: secret_key, iv: iv)
=> "\x12\x9A\x81*U\xCFT\x91\xB7;\xAF\xF2I]\x9C@L\xD5\xB8;\x00\x87\xF3\x82yS(r\x90\xC8\x86\xBB\x13\x92\xA83$O"

These are both using encryptor 3.0.0.

Unencrypt via database query

Is there any way to unencrypt an encrypted column through active record? Or more importantly, is there a way to unencrypt straight with SQL?

Ruby 2 Error: TypeError: no implicit conversion of Symbol into String

I had already posted this issue in the attr_encrypted gem issue page, but iv realized its an issue with this gem.

More details here: attr-encrypted/attr_encrypted#60

When setting the value of an encrypted attribute I get the error:

TypeError: no implicit conversion of Symbol into String

Quick example:

attr_encrypted :content, :key => :note_key, :unless => :locked
user = User.new
user.content = "Some encrypted content"
It's worth mentioning that this code has been working fine using Ruby 1.9.3 and Rails 3.2 for many months.

Environment:
Rails 3.2
Ruby 2.0.0-p247

Trace
TypeError: no implicit conversion of Symbol into String
from /usr/local/rvm/gems/ruby-2.0.0-p247@sampleapp/gems/encryptor-1.1.3/lib/encryptor.rb:58:in pkcs5_keyivgen'
from /usr/local/rvm/gems/ruby-2.0.0-p247@sampleapp/gems/encryptor-1.1.3/lib/encryptor.rb:58:incrypt'
from /usr/local/rvm/gems/ruby-2.0.0-p247@sampleapp/gems/encryptor-1.1.3/lib/encryptor.rb:31:in encrypt'
from /usr/local/rvm/gems/ruby-2.0.0-p247@sampleapp/gems/attr_encrypted-1.2.1/lib/attr_encrypted.rb:205:inencrypt'
from /usr/local/rvm/gems/ruby-2.0.0-p247@sampleapp/gems/attr_encrypted-1.2.1/lib/attr_encrypted.rb:281:in encrypt'
from (irb):2

ArgumentError: data must not be empty

When upgrading the gem from version 1.1.3 to 3.0.0 (or 2.0.0), I get the error:
"ArgumentError: data must not be empty" on a Encryptor.decrypt call
I'm calling the decrypt method with the same value as before (iv is 12 bytes instead of 16).
dcrypted_value = Encryptor.decrypt unpacked, :key => the_key, :iv => the_iv, :salt => the_salt

Test failures with Ruby2.7

Hi there,

There are some test failures:

Finished in 0.024393s, 901.8873 runs/s, 860.8924 assertions/s.

  1) Error:
CompatibilityTest#test_decrypt_with_iv:
ArgumentError: key must be 32 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:72:in `key='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:72:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:49:in `decrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/compatibility_test.rb:47:in `test_decrypt_with_iv'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

  2) Error:
CompatibilityTest#test_encrypt_with_iv_and_salt:
ArgumentError: iv must be 16 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `iv='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:36:in `encrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/compatibility_test.rb:72:in `test_encrypt_with_iv_and_salt'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

  3) Error:
CompatibilityTest#test_ciphertext_encrypted_with_v2_decrypts_with_v2_gcm_iv_option:
ArgumentError: iv must be 12 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:66:in `iv='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:66:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:49:in `decrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/compatibility_test.rb:98:in `test_ciphertext_encrypted_with_v2_decrypts_with_v2_gcm_iv_option'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

  4) Error:
CompatibilityTest#test_decrypt_with_iv_and_salt:
ArgumentError: iv must be 16 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `iv='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:49:in `decrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/compatibility_test.rb:86:in `test_decrypt_with_iv_and_salt'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

  5) Error:
CompatibilityTest#test_encrypt_with_iv:
ArgumentError: key must be 32 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:72:in `key='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:72:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:36:in `encrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/compatibility_test.rb:23:in `test_encrypt_with_iv'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

  6) Failure:
CompatibilityTest#test_ciphertext_encrypted_with_v2_does_not_decrypt_without_v2_gcm_iv_option [/tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/compatibility_test.rb:103]:
[OpenSSL::Cipher::CipherError] exception expected, not
Class: <ArgumentError>
Message: <"iv must be 12 bytes">
---Backtrace---
/usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `iv='
/usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `crypt'
/usr/lib/ruby/vendor_ruby/encryptor.rb:49:in `decrypt'
/tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/compatibility_test.rb:105:in `block in test_ciphertext_encrypted_with_v2_does_not_decrypt_without_v2_gcm_iv_option'
/usr/lib/ruby/vendor_ruby/minitest/assertions.rb:398:in `assert_raises'
/tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/compatibility_test.rb:103:in `test_ciphertext_encrypted_with_v2_does_not_decrypt_without_v2_gcm_iv_option'
/usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
/usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
/usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
/usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
/usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
/usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
/usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
/usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
/usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
/usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
/usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
/usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
/usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
/usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
/usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
/usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
/usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
/usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
/usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
/usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
/usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'
---------------

  7) Error:
EncryptorTest#test_should_use_iv_to_initialize_encryption:
ArgumentError: iv must be 12 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `iv='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:36:in `encrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/encryptor_test.rb:85:in `block (2 levels) in <class:EncryptorTest>'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

  8) Error:
EncryptorTest#test_should_yield_block_with_cipher_and_options:
ArgumentError: iv must be 12 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `iv='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:36:in `encrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/encryptor_test.rb:78:in `block in <class:EncryptorTest>'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

  9) Error:
EncryptorTest#test_should_use_authentication_data_if_it_is_specified:
ArgumentError: iv must be 12 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `iv='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:36:in `encrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/encryptor_test.rb:101:in `block (2 levels) in <class:EncryptorTest>'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

 10) Error:
EncryptorTest#test_should_use_the_default_algorithm_if_one_is_not_specified:
ArgumentError: iv must be 12 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `iv='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:36:in `encrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/encryptor_test.rb:48:in `block in <class:EncryptorTest>'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

 11) Error:
EncryptorTest#test_should_use_the_default_authentication_data_if_it_is_not_specified:
ArgumentError: iv must be 12 bytes
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `iv='
    /usr/lib/ruby/vendor_ruby/encryptor.rb:79:in `crypt'
    /usr/lib/ruby/vendor_ruby/encryptor.rb:36:in `encrypt'
    /tmp/autopkgtest-lxc.u2pr2pbo/downtmp/build.9EI/src/test/encryptor_test.rb:93:in `block (2 levels) in <class:EncryptorTest>'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:98:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:195:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:95:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:270:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:94:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:211:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:93:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:1029:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:339:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:326:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:325:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:365:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:352:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:164:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:141:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:68:in `block in autorun'

22 runs, 21 assertions, 1 failures, 10 errors, 0 skips
rake aborted!
Command failed with status (1): [ruby -w -I"test"  "/usr/lib/ruby/vendor_ruby/rake/rake_test_loader.rb" "test/compatibility_test.rb" "test/encryptor_string_test.rb" "test/encryptor_test.rb" "test/legacy_encryptor_string_test.rb" "test/legacy_encryptor_test.rb" -v]

Error with legacy / insecure mode?

Maybe I'm doing something obviously incorrect here? I'm copy/pasting the encrypted value.

irb(main):048:0> Encryptor.default_options
=> {:algorithm=>"aes-256-gcm", :auth_data=>"", :insecure_mode=>true, :hmac_iterations=>2000, :v2_gcm_iv=>true}
irb(main):049:0> Encryptor.encrypt(key: secret, value: 'foo')
=> "X\xC6[>\xB6\x98\x14\b+\x93\x86R\xAC\x94\x9B\xC9\xAE\xDD\x1A"
irb(main):050:0> Encryptor.decrypt(key: secret, value: "X\xC6[>\xB6\x98\x14\b+\x93\x86R\xAC\x94\x9B\xC9\xAE\xDD\x1A")
OpenSSL::Cipher::CipherError: unable to set AEAD tag
        from /home/sguth/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/encryptor-3.0.0/lib/encryptor.rb:91:in `auth_tag='
        from /home/sguth/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/encryptor-3.0.0/lib/encryptor.rb:91:in `crypt'
        from /home/sguth/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/encryptor-3.0.0/lib/encryptor.rb:49:in `decrypt'
        from (irb):50
        from /home/sguth/.rbenv/versions/2.4.1/bin/irb:11:in `<main>'
irb(main):051:0>

Test failure - Bytesize is deprecated

NoMethodError:
undefined method `bytesize' for 232240348473709411:Integer
Did you mean? bytes

rvm/gems/ruby-2.6.6/gems/encryptor-3.0.0/lib/encryptor.rb:60:in crypt' rvm/gems/ruby-2.6.6/gems/encryptor-3.0.0/lib/encryptor.rb:36:in encrypt'

Fix
use bytes instead of bitesize

Encryptor doesn't provide any option for an integrity-check value

None of the block cipher modes available in OpenSSL provide any integrity protection. CBC provides a bit of error propagation which sometimes causes a corrupted ciphertext to raise "wrong final block length," but this isn't a guaranteed behavior.

I'd like to contribute an improvement to Encryptor to take care of this. It would work as follows:

  1. The constructor accepts two new options, :integrity_key and :integrity_algorithm
  2. If present, :integrity_key will be used to initialize an HMAC specified by :integrity_algorithm
  3. If the HMAC is present during encrypt, Encryptor will prepend an HMAC of the ciphertext to every ciphertext it generates, after encrypt but before encode.
  4. If HMAC is present during decrypt, Encryptor will consume the first N bytes of each message and compare it against an HMAC of the remainder of the ciphertext, after decode but before decrypt.
  5. If any HMAC fails, Encryptor will raise a suitable OpenSSL exception -- or possibly just propagate whatever HMAC raises

Does this seem like a reasonable contribution? Let me know.

Failed to decrypt and encrypted string: CipherError

Hi there.

I seem to have found some production errors reflecting a failure to decrypt certain string. The error message is:

OpenSSL::Cipher::CipherError: bad decrypt
    from /Users/chris/.rvm/gems/ruby-1.8.7-p334@frontend/gems/encryptor-1.1.3/lib/encryptor.rb:62:in `final'
    from /Users/chris/.rvm/gems/ruby-1.8.7-p334@frontend/gems/encryptor-1.1.3/lib/encryptor.rb:62:in `crypt'
    from /Users/chris/.rvm/gems/ruby-1.8.7-p334@frontend/gems/encryptor-1.1.3/lib/encryptor.rb:44:in `decrypt'

My key is an 128 hex character string: Are there any restrictions on the key value I am unaware of?

Thanks.

Test using GCM with IV option failing

Related to #22 , #22 (comment) and https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=842432

Ruby version: 2.3.3
Debian bug report: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=880276
Complete log: http://aws-logs.debian.net/2017/10/30/ruby-encryptor_3.0.0-1_unstable.log

Relevant Log

Run options: -v --seed 47501

# Running:

EncryptorTest#test_should_raise_argument_error_if_key_is_not_specified = 0.00 s = .
EncryptorTest#test_should_use_the_default_authentication_data_if_it_is_not_specified = 0.01 s = .
EncryptorTest#test_should_use_authentication_data_if_it_is_specified = 0.01 s = .
EncryptorTest#test_should_use_the_default_algorithm_if_one_is_not_specified = 0.01 s = .
EncryptorTest#test_should_use_iv_to_initialize_encryption = 0.01 s = .
EncryptorTest#test_should_yield_block_with_cipher_and_options = 0.00 s = .
EncryptorTest#test_should_raise_argument_error_if_iv_is_not_specified = 0.00 s = .
EncryptorTest#test_should_raise_argument_error_if_key_is_too_short = 0.00 s = .
EncryptorTest#test_should_have_a_default_algorithm = 0.00 s = .
EncryptorTest#test_should_raise_argument_error_if_iv_is_too_short = 0.00 s = .
LegacyEncryptorTest#test_should_raise_argument_error_if_key_is_not_specified = 0.00 s = .
LegacyEncryptorTest#test_should_use_the_default_algorithm_if_one_is_not_specified = 0.00 s = .
LegacyEncryptorTest#test_should_yield_block_with_cipher_and_options = 0.00 s = .
LegacyEncryptorTest#test_should_have_a_default_algorithm = 0.00 s = .
CompatibilityTest#test_encrypt_with_iv = 0.00 s = .
CompatibilityTest#test_ciphertext_encrypted_with_v2_decrypts_with_v2_gcm_iv_option = 0.00 s = E
CompatibilityTest#test_decrypt_without_iv = 0.00 s = .
CompatibilityTest#test_encrypt_with_iv_and_salt = 0.00 s = .
CompatibilityTest#test_encrypt_without_iv = 0.00 s = .
CompatibilityTest#test_decrypt_with_iv_and_salt = 0.00 s = .
CompatibilityTest#test_ciphertext_encrypted_with_v2_does_not_decrypt_without_v2_gcm_iv_option = 0.00 s = .
CompatibilityTest#test_decrypt_with_iv = 0.00 s = .

Finished in 0.051692s, 425.6001 runs/s, 696.4365 assertions/s.

  1) Error:
CompatibilityTest#test_ciphertext_encrypted_with_v2_decrypts_with_v2_gcm_iv_option:
OpenSSL::Cipher::CipherError: 
    /<<PKGBUILDDIR>>/lib/encryptor.rb:98:in `final'
    /<<PKGBUILDDIR>>/lib/encryptor.rb:98:in `crypt'
    /<<PKGBUILDDIR>>/lib/encryptor.rb:49:in `decrypt'
    /<<PKGBUILDDIR>>/test/compatibility_test.rb:98:in `test_ciphertext_encrypted_with_v2_decrypts_with_v2_gcm_iv_option'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:107:in `block (3 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:204:in `capture_exceptions'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:104:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:255:in `time_it'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:103:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:350:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:275:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest/test.rb:102:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:839:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:324:in `run_one_method'
    /usr/lib/ruby/vendor_ruby/minitest.rb:311:in `block (2 levels) in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:310:in `each'
    /usr/lib/ruby/vendor_ruby/minitest.rb:310:in `block in run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:350:in `on_signal'
    /usr/lib/ruby/vendor_ruby/minitest.rb:337:in `with_info_handler'
    /usr/lib/ruby/vendor_ruby/minitest.rb:309:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:159:in `block in __run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:159:in `map'
    /usr/lib/ruby/vendor_ruby/minitest.rb:159:in `__run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:136:in `run'
    /usr/lib/ruby/vendor_ruby/minitest.rb:63:in `block in autorun'

22 runs, 36 assertions, 0 failures, 1 errors, 0 skips
rake aborted!
Command failed with status (1): [ruby -w -I"test"  "/usr/lib/ruby/vendor_ruby/rake/rake_test_loader.rb" "test/compatibility_test.rb" "test/encryptor_string_test.rb" "test/encryptor_test.rb" "test/legacy_encryptor_string_test.rb" "test/legacy_encryptor_test.rb" -v]

My understanding is that CVE-2016-7798 was fixed in Ruby 2.3.3 itself. And with #22 , this was fixed also on encryptor end. I don't understand much of the code, but was the comment

Hopefully there won't be too much fallout

actually anticipating something like the above log? If so, what can we do to fix it?

New gem release

Will there be a new gem release any time soon? The latest on Rubygems lacks the :salt option. I'm extracting some functionality dependent on this gem from another project, and while using the :git option in a Gemfile works fine in most projects, specifying a git gem dependency in another gem itself isn't possible. Even a .pre push would be great.

Thanks for your work on the library.

Fails silently with Passenger Phusion

I'm having an issue where the following line

Encryptor.encrypt(:value => new_number, :key => MY_KEY)

works on Unicorn and in tests, but segfaults Passenger with no error output that I can find. MY_KEY is a placeholder for a 32-character hex string

Will update when I've fixed it unless you have a solution to the issue already

Help with decrypting data using aes-256-gcm and encryptor version 1.3.0

Hi Team,

We use aes-256-gcm and pass it to encrypt and decrypt function to override default algorithm. However, recently due to a bug we switched back to encryptor version. 1.3.0 and encrypted some data using the encryption logic. encryption didn't raise an error however, I am not able to decrypt the same data now. Can you please suggest if "aes-256-gcm" is supported by encryptor v1.3.0 and that if there is any way to decrypt data encrypted using "aes-256-gcm" algorithm and encryptor version. 1.3.0.

Thank you, Attaching a reproducible test case (ruby code) here if that helps -

require 'base64'
require 'encryptor'

def algorithm
  'aes-256-gcm'
end

data_key = "123456789101112"

def cipher
  OpenSSL::Cipher.new(algorithm).tap do |cipher|
    # Required before '#random_key' or '#random_iv' can be called.
    # http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html#method-i-encrypt
    cipher.encrypt
  end
end

iv = cipher.random_iv
salt = SecureRandom.random_bytes(64)
encrypted_content   = Encryptor.encrypt("himanshu", { key: data_key, iv: iv, salt: salt, algorithm: algorithm })

truncated_iv = iv.size > cipher.iv_len ? iv[0, cipher.iv_len] : iv
Encryptor.decrypt(encrypted_content, { key: data_key, iv: truncated_iv, salt: salt, algorithm: algorithm })

Encryptor class has gotten worse according to Code Climate

Hi. I noticed you have a Code Climate badge, so I'm assuming you care about the quality of this repo's code. I noticed that the latest commits have resulted in a worse grade on Code Climate. Is this something you care about and are planning to address?

The general rule of thumb I follow when working on projects that use Code Climate is that a pull request that results in a worse grade does not get merged.

I was wondering what your thoughts are on this matter.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.