Diff
Modified: trunk/jopenssl/src/java/org/jruby/ext/openssl/Cipher.java (1110 => 1111)
--- trunk/jopenssl/src/java/org/jruby/ext/openssl/Cipher.java 2008-08-12 15:54:11 UTC (rev 1110)
+++ trunk/jopenssl/src/java/org/jruby/ext/openssl/Cipher.java 2008-08-13 13:18:12 UTC (rev 1111)
@@ -57,7 +57,6 @@
* @author <a href="" PROTECTED]">Ola Bini</a>
*/
public class Cipher extends RubyObject {
-
// set to enable debug output
private static final boolean DEBUG = false;
private static ObjectAllocator CIPHER_ALLOCATOR = new ObjectAllocator() {
@@ -197,7 +196,8 @@
//private IRubyObject[] modeParams;
private boolean ciphInited = false;
private byte[] key;
- private byte[] iv;
+ private byte[] realIV;
+ private byte[] orgIV;
private String padding;
void dumpVars() {
@@ -214,8 +214,9 @@
System.out.println("encryptMode = " + encryptMode);
System.out.println("ciphInited = " + ciphInited);
System.out.println("key.length = " + (key == null ? 0 : key.length));
- System.out.println("iv.length = " + (iv == null ? 0 : iv.length));
+ System.out.println("iv.length = " + (this.realIV == null ? 0 : this.realIV.length));
System.out.println("padding = " + padding);
+ System.out.println("ciphAlgo = " + ciph.getAlgorithm());
System.out.println("*******************************");
}
@@ -293,12 +294,13 @@
} else {
key = null;
}
- if(((Cipher)obj).iv != null) {
- iv = new byte[((Cipher)obj).iv.length];
- System.arraycopy(((Cipher)obj).iv,0,iv,0,iv.length);
+ if(((Cipher)obj).realIV != null) {
+ this.realIV = new byte[((Cipher)obj).realIV.length];
+ System.arraycopy(((Cipher)obj).realIV,0,this.realIV,0,this.realIV.length);
} else {
- iv = null;
+ this.realIV = null;
}
+ this.orgIV = this.realIV;
padding = ((Cipher)obj).padding;
ciph = getCipher();
@@ -362,7 +364,8 @@
if(ivBytes.length < ivLen) {
throw new RaiseException(getRuntime(), ciphErr, "iv length to short", true);
}
- this.iv = ivBytes;
+ this.realIV = ivBytes;
+ this.orgIV = this.realIV;
return iv;
}
@@ -414,24 +417,28 @@
OpenSSLImpl.KeyAndIv result = OpenSSLImpl.EVP_BytesToKey(keyLen,ivLen,digest,iv,pass,2048);
this.key = result.getKey();
- this.iv = iv;
+ this.realIV = iv;
+ this.orgIV = this.realIV;
}
}
@JRubyMethod(optional=2)
public IRubyObject encrypt(IRubyObject[] args) {
+ this.realIV = orgIV;
init(args, true);
return this;
}
@JRubyMethod(optional=2)
public IRubyObject decrypt(IRubyObject[] args) {
+ this.realIV = orgIV;
init(args, false);
return this;
}
@JRubyMethod
public IRubyObject reset() {
+ this.realIV = orgIV;
doInitialize();
return this;
}
@@ -501,7 +508,8 @@
OpenSSLImpl.KeyAndIv result = OpenSSLImpl.EVP_BytesToKey(keyLen, ivLen, digest, salt, pass, iter);
this.key = result.getKey();
- this.iv = result.getIv();
+ this.realIV = result.getIv();
+ this.orgIV = this.realIV;
doInitialize();
@@ -516,9 +524,9 @@
ciphInited = true;
try {
assert (key.length * 8 == keyLen) || (key.length == keyLen) : "Key wrong length";
- assert (iv.length * 8 == ivLen) || (iv.length == ivLen): "IV wrong length";
- if(!"ECB".equalsIgnoreCase(cryptoMode) && this.iv != null) {
- this.ciph.init(encryptMode ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE, new SimpleSecretKey(this.key), new IvParameterSpec(this.iv));
+ assert (this.realIV.length * 8 == ivLen) || (this.realIV.length == ivLen): "IV wrong length";
+ if(!"ECB".equalsIgnoreCase(cryptoMode) && this.realIV != null) {
+ this.ciph.init(encryptMode ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE, new SimpleSecretKey(this.key), new IvParameterSpec(this.realIV));
} else {
this.ciph.init(encryptMode ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE, new SimpleSecretKey(this.key));
}
@@ -528,11 +536,12 @@
}
}
+ private byte[] lastIv = null;
+
@JRubyMethod
public IRubyObject update(IRubyObject data) {
if (DEBUG) System.out.println("*** update ["+data+"]");
- //TODO: implement correctly
byte[] val = data.convertToString().getBytes();
if(val.length == 0) {
throw getRuntime().newArgumentError("data must not be empty");
@@ -547,10 +556,20 @@
byte[] out = ciph.update(val);
if(out != null) {
str = out;
+
+ if(this.realIV != null) {
+ if(lastIv == null) {
+ lastIv = new byte[ivLen];
+ }
+ byte[] tmpIv = encryptMode ? out : val;
+ if(tmpIv.length >= ivLen) {
+ System.arraycopy(tmpIv, tmpIv.length-ivLen, lastIv, 0, ivLen);
+ }
+ }
}
} catch(Exception e) {
e.printStackTrace();
- throw new RaiseException(getRuntime(), ciphErr, null, true);
+ throw new RaiseException(getRuntime(), ciphErr, e.getMessage(), true);
}
return RubyString.newString(getRuntime(), new ByteList(str,false));
@@ -568,13 +587,26 @@
doInitialize();
}
- //TODO: implement correctly
ByteList str = new ByteList(ByteList.NULL_ARRAY);
try {
byte[] out = ciph.doFinal();
if(out != null) {
str = new ByteList(out,false);
+ if(this.realIV != null && encryptMode) {
+ if(lastIv == null) {
+ lastIv = new byte[ivLen];
+ }
+ byte[] tmpIv = out;
+ if(tmpIv.length >= ivLen) {
+ System.arraycopy(tmpIv, tmpIv.length-ivLen, lastIv, 0, ivLen);
+ }
+ }
}
+
+ if(this.realIV != null) {
+ this.realIV = lastIv;
+ doInitialize();
+ }
} catch(Exception e) {
throw new RaiseException(getRuntime(), ciphErr, e.getMessage(), true);
}
Modified: trunk/jopenssl/src/java/org/jruby/ext/openssl/Digest.java (1110 => 1111)
--- trunk/jopenssl/src/java/org/jruby/ext/openssl/Digest.java 2008-08-12 15:54:11 UTC (rev 1110)
+++ trunk/jopenssl/src/java/org/jruby/ext/openssl/Digest.java 2008-08-13 13:18:12 UTC (rev 1111)
@@ -114,6 +114,9 @@
private StringBuffer data;
private String name;
+ public String getRealName() {
+ return transformDigest(name);
+ }
public String getName() {
return name;
Modified: trunk/jopenssl/src/java/org/jruby/ext/openssl/PKey.java (1110 => 1111)
--- trunk/jopenssl/src/java/org/jruby/ext/openssl/PKey.java 2008-08-12 15:54:11 UTC (rev 1110)
+++ trunk/jopenssl/src/java/org/jruby/ext/openssl/PKey.java 2008-08-13 13:18:12 UTC (rev 1111)
@@ -131,12 +131,14 @@
}
byte[] sigBytes = ((RubyString)sig).getBytes();
byte[] dataBytes = ((RubyString)data).getBytes();
- String algorithm = ((Digest)digest).getName() + "with" + getAlgorithm();
+ String algorithm = ((Digest)digest).getRealName() + "with" + getAlgorithm();
boolean valid;
try {
// note: not specifying "BC" provider here, as that would fail if
// BC wasn't plugged in (as it would not be for, say, Net::SSH)
- Signature signature = Signature.getInstance(algorithm);
+ Signature signature = OpenSSLReal.PROVIDER == null ?
+ Signature.getInstance(algorithm) :
+ Signature.getInstance(algorithm, OpenSSLReal.PROVIDER);
signature.initVerify(getPublicKey());
signature.update(dataBytes);
valid = signature.verify(sigBytes);
Modified: trunk/jopenssl/test/openssl/test_cipher.rb (1110 => 1111)
--- trunk/jopenssl/test/openssl/test_cipher.rb 2008-08-12 15:54:11 UTC (rev 1110)
+++ trunk/jopenssl/test/openssl/test_cipher.rb 2008-08-13 13:18:12 UTC (rev 1111)
@@ -1,3 +1,10 @@
+if defined?(JRUBY_VERSION)
+ require "java"
+ base = File.join(File.dirname(__FILE__), '..', '..')
+ $CLASSPATH << File.join(base, 'pkg', 'classes')
+ $CLASSPATH << File.join(base, 'lib', 'bcprov-jdk14-139.jar')
+end
+
begin
require "openssl"
rescue LoadError
Modified: trunk/jopenssl/test/test_cipher.rb (1110 => 1111)
--- trunk/jopenssl/test/test_cipher.rb 2008-08-12 15:54:11 UTC (rev 1110)
+++ trunk/jopenssl/test/test_cipher.rb 2008-08-13 13:18:12 UTC (rev 1111)
@@ -1,3 +1,10 @@
+if defined?(JRUBY_VERSION)
+ require "java"
+ base = File.dirname(__FILE__)
+ $CLASSPATH << File.join(base, '..', 'pkg', 'classes')
+ $CLASSPATH << File.join(base, '..', 'lib', 'bcprov-jdk14-139.jar')
+end
+
begin
require "openssl"
rescue LoadError
@@ -12,4 +19,63 @@
data = ""
data << enc.final
end
+
+ IV_TEMPLATE = "aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjj"
+ KEY_TEMPLATE = "aaaabbbbccccddddeeeeffffgggghhhhiiiijjjjj"
+
+ # JRUBY-1692
+ def test_repeated_des
+ do_repeated_test(
+ "des-ede3-cbc",
+ "foobarbazboofarf",
+ ":\022Q\211ex\370\332\374\274\214\356\301\260V\025",
+ "B\242\3531\003\362\3759\363s\203\374\240\030|\230"
+ )
+ end
+
+ # JRUBY-1692
+ def test_repeated_aes
+ do_repeated_test(
+ "aes-128-cbc",
+ "foobarbazboofarf",
+ "\342\260Y\344\306\227\004^\272|/\323<\016,\226",
+ "jqO\305/\211\216\b\373\300\274\bw\213]\310"
+ )
+ end
+
+ private
+ def do_repeated_test(algo, string, enc1, enc2)
+ do_repeated_encrypt_test(algo, string, enc1, enc2)
+ do_repeated_decrypt_test(algo, string, enc1, enc2)
+ end
+
+ def do_repeated_encrypt_test(algo, string, result1, result2)
+ cipher = OpenSSL::Cipher::Cipher.new(algo)
+ cipher.encrypt
+
+ cipher.padding = 0
+ cipher.iv = IV_TEMPLATE[0, cipher.iv_len]
+ cipher.key = KEY_TEMPLATE[0, cipher.key_len]
+
+ assert_equal result1, cipher.update(string)
+ cipher.final
+
+ assert_equal result2, cipher.update(string)
+ cipher.final
+ end
+
+ def do_repeated_decrypt_test(algo, result, string1, string2)
+ cipher = OpenSSL::Cipher::Cipher.new(algo)
+ cipher.decrypt
+
+ cipher.padding = 0
+ cipher.iv = IV_TEMPLATE[0, cipher.iv_len]
+ cipher.key = KEY_TEMPLATE[0, cipher.key_len]
+
+ assert_equal result, cipher.update(string1)
+ cipher.final
+
+ assert_equal result, cipher.update(string2)
+ cipher.final
+ end
end