|
38 | 38 | import java.security.MessageDigest;
|
39 | 39 | import java.security.NoSuchAlgorithmException;
|
40 | 40 | import java.security.Provider;
|
| 41 | +import java.security.spec.AlgorithmParameterSpec; |
41 | 42 | import java.util.HashMap;
|
42 | 43 | import java.util.LinkedHashMap;
|
43 | 44 | import java.util.List;
|
44 | 45 | import java.util.Map;
|
45 | 46 | import static javax.crypto.Cipher.DECRYPT_MODE;
|
46 | 47 | import static javax.crypto.Cipher.ENCRYPT_MODE;
|
47 | 48 | import javax.crypto.NoSuchPaddingException;
|
| 49 | +import javax.crypto.spec.GCMParameterSpec; |
48 | 50 | import javax.crypto.spec.IvParameterSpec;
|
49 | 51 | import javax.crypto.spec.RC2ParameterSpec;
|
50 | 52 |
|
51 | 53 | import org.jruby.Ruby;
|
52 | 54 | import org.jruby.RubyArray;
|
53 | 55 | import org.jruby.RubyClass;
|
| 56 | +import org.jruby.RubyInteger; |
54 | 57 | import org.jruby.RubyModule;
|
55 | 58 | import org.jruby.RubyNumeric;
|
56 | 59 | import org.jruby.RubyObject;
|
@@ -611,7 +614,9 @@ public int getIvLength() {
|
611 | 614 |
|
612 | 615 | if ( ivLength == -1 ) {
|
613 | 616 | if ( "AES".equals(base) ) {
|
614 |
| - ivLength = 16; |
| 617 | + ivLength = 16; // OpenSSL defaults to 12 |
| 618 | + // NOTE: we can NOT handle 12 for non GCM mode |
| 619 | + if ( "GCM".equals(mode) ) ivLength = 12; |
615 | 620 | }
|
616 | 621 | //else if ( "DES".equals(base) ) {
|
617 | 622 | // ivLength = 8;
|
@@ -790,22 +795,22 @@ public IRubyObject initialize_copy(final IRubyObject obj) {
|
790 | 795 | }
|
791 | 796 |
|
792 | 797 | @JRubyMethod
|
793 |
| - public IRubyObject name() { |
| 798 | + public final RubyString name() { |
794 | 799 | return getRuntime().newString(name);
|
795 | 800 | }
|
796 | 801 |
|
797 | 802 | @JRubyMethod
|
798 |
| - public IRubyObject key_len() { |
| 803 | + public final RubyInteger key_len() { |
799 | 804 | return getRuntime().newFixnum(keyLength);
|
800 | 805 | }
|
801 | 806 |
|
802 | 807 | @JRubyMethod
|
803 |
| - public IRubyObject iv_len() { |
| 808 | + public final RubyInteger iv_len() { |
804 | 809 | return getRuntime().newFixnum(ivLength);
|
805 | 810 | }
|
806 | 811 |
|
807 | 812 | @JRubyMethod(name = "key_len=", required = 1)
|
808 |
| - public IRubyObject set_key_len(IRubyObject len) { |
| 813 | + public final IRubyObject set_key_len(IRubyObject len) { |
809 | 814 | this.keyLength = RubyNumeric.fix2int(len);
|
810 | 815 | return len;
|
811 | 816 | }
|
@@ -959,7 +964,7 @@ private void updateCipher(final String name, final String padding) {
|
959 | 964 | cipher = getCipherInstance();
|
960 | 965 | }
|
961 | 966 |
|
962 |
| - javax.crypto.Cipher getCipherInstance() { |
| 967 | + final javax.crypto.Cipher getCipherInstance() { |
963 | 968 | try {
|
964 | 969 | return getCipherInstance(realName, false);
|
965 | 970 | }
|
@@ -1040,15 +1045,22 @@ else if ( "RC4".equalsIgnoreCase(cryptoBase) ) {
|
1040 | 1045 | );
|
1041 | 1046 | }
|
1042 | 1047 | else {
|
| 1048 | + final AlgorithmParameterSpec ivSpec; |
| 1049 | + if ( "GCM".equalsIgnoreCase(cryptoMode) ) { // e.g. 'aes-128-gcm' |
| 1050 | + ivSpec = new GCMParameterSpec(this.ivLength * 8, this.realIV); |
| 1051 | + } |
| 1052 | + else { |
| 1053 | + ivSpec = new IvParameterSpec(this.realIV); |
| 1054 | + } |
1043 | 1055 | cipher.init(encryptMode ? ENCRYPT_MODE : DECRYPT_MODE,
|
1044 | 1056 | new SimpleSecretKey(getCipherAlgorithm(), this.key),
|
1045 |
| - new IvParameterSpec(this.realIV) |
| 1057 | + ivSpec |
1046 | 1058 | );
|
1047 | 1059 | }
|
1048 | 1060 | }
|
1049 | 1061 | }
|
1050 | 1062 | catch (InvalidKeyException e) {
|
1051 |
| - throw newCipherError(runtime, e + ": possibly you need to install Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for your JRE"); |
| 1063 | + throw newCipherError(runtime, e + "\n possibly you need to install Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files for your JRE"); |
1052 | 1064 | }
|
1053 | 1065 | catch (Exception e) {
|
1054 | 1066 | debugStackTrace(runtime, e);
|
|
0 commit comments