· 7 years ago · Jan 22, 2019, 12:40 AM
1class SecretData < ActiveRecord::Base
2 mysecret = "mylittlesecret"
3
4 attr_encrypted :data1, :key=>mysecret, :algorithm => "aes-256-cbc"
5 attr_encrypted :data2, :key=>mysecret, :algorithm => "aes-256-cbc"
6
7 ...
8end
9
10cyE3jDkKc99GVB8TiUlBxQ==
11sqcbOnBTl6yy3wwjkl0qhA==
12
13echo cyE3jDkKc99GVB8TiUlBxQ== | openssl aes-256-cbc -a -d (and type "mylittlesecret" as the password)
14
15Key key = generateKey();
16Cipher c = Cipher.getInstance(ALGO);
17c.init(Cipher.DECRYPT_MODE, key);
18byte[] decordedValue = new BASE64Decoder().decodeBuffer(encryptedData);
19byte[] decValue = c.doFinal(decordedValue);
20String decryptedValue = new String(decValue);
21
22irb(main):069:0> Encryptor.decrypt(Base64.decode64("cyE3jDkKc99GVB8TiUlBxQ=="), ,key=>'mylittlesecret')
23=> "data1-value"
24
25public static byte[][] EVP_BytesToKey(int key_len, int iv_len, MessageDigest md,
26 byte[] salt, byte[] data, int count) {
27 byte[][] both = new byte[2][];
28 byte[] key = new byte[key_len];
29 int key_ix = 0;
30 byte[] iv = new byte[iv_len];
31 int iv_ix = 0;
32 both[0] = key;
33 both[1] = iv;
34 byte[] md_buf = null;
35 int nkey = key_len;
36 int niv = iv_len;
37 int i = 0;
38 if (data == null) {
39 return both;
40 }
41 int addmd = 0;
42 for (;;) {
43 md.reset();
44 if (addmd++ > 0) {
45 md.update(md_buf);
46 }
47 md.update(data);
48 if (null != salt) {
49 md.update(salt, 0, 8);
50 }
51 md_buf = md.digest();
52 for (i = 1; i < count; i++) {
53 md.reset();
54 md.update(md_buf);
55 md_buf = md.digest();
56 }
57 i = 0;
58 if (nkey > 0) {
59 for (;;) {
60 if (nkey == 0)
61 break;
62 if (i == md_buf.length)
63 break;
64 key[key_ix++] = md_buf[i];
65 nkey--;
66 i++;
67 }
68 }
69 if (niv > 0 && i != md_buf.length) {
70 for (;;) {
71 if (niv == 0)
72 break;
73 if (i == md_buf.length)
74 break;
75 iv[iv_ix++] = md_buf[i];
76 niv--;
77 i++;
78 }
79 }
80 if (nkey == 0 && niv == 0) {
81 break;
82 }
83 }
84 for (i = 0; i < md_buf.length; i++) {
85 md_buf[i] = 0;
86 }
87 return both;
88 }
89
90def self.encrypt(options)
91
92 plaintext = options[:value]
93 return true if plaintext.blank?
94
95 cipher = OpenSSL::Cipher::Cipher.new(@@cipher_type)
96 cipher.encrypt
97
98 iv = cipher.random_iv
99 salt = (0 ... @@salt_length).map{65.+(rand(25)).chr}.join # random salt
100 key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(@@password, salt, @@pkbdf_num_iters, cipher.key_len)
101
102 cipher.key = key
103 cipher.iv = iv
104
105 enc_data = cipher.update(plaintext)
106 enc_data << cipher.final
107
108 final_data = salt << iv << enc_data
109 Base64.strict_encode64(final_data)
110end
111
112def self.decrypt(options)
113
114 ciphertext = options[:value]
115 return true if ciphertext.blank?
116
117
118 cipher = OpenSSL::Cipher::Cipher.new(@@cipher_type)
119 cipher.decrypt
120
121 cipher_data = Base64.decode64(ciphertext)
122
123 salt = cipher_data[0 .. @@salt_length-1]
124 iv = cipher_data[@@salt_length .. @@salt_length+cipher.iv_len]
125 enc_data = cipher_data[@@salt_length+cipher.iv_len .. -1] # the rest
126
127 key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(@@password, salt, @@pkbdf_num_iters, cipher.key_len)
128
129 cipher.key = key
130 cipher.iv = iv
131
132 plaintext = cipher.update(enc_data)
133 plaintext << cipher.final
134
135 plaintext
136 end
137
138public String decrypt(String ciphertext) throws Exception {
139 byte[] crypt = Base64.decodeBase64(ciphertext);
140
141 // parse the encrypted data and get salt and IV
142 byte[] salt = Arrays.copyOfRange(crypt, 0, saltLength);
143 byte[] iv = Arrays.copyOfRange(crypt, saltLength, saltLength + ivLength);
144 byte[] encryptedData = Arrays.copyOfRange(crypt, saltLength + ivLength, crypt.length);
145
146 // generate key from salt and password
147 SecretKeyFactory f = SecretKeyFactory.getInstance(secretKeyName);
148 KeySpec ks = new PBEKeySpec(password.toCharArray(), salt, pbkdfNumIters, keyLength);
149 SecretKey s = f.generateSecret(ks);
150 Key keySpec = new SecretKeySpec(s.getEncoded(),"AES");
151
152 // initialize the cipher object with the key and IV
153 Cipher cipher = Cipher.getInstance(cipherAlgo);
154 IvParameterSpec ivSpec = new IvParameterSpec(iv);
155 cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
156
157 // decrypt
158 byte[] decBytes = cipher.doFinal(encryptedData);
159
160 return new String(decBytes);
161}