|
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