Diff
Modified: trunk/jopenssl/src/java/org/jruby/ext/openssl/PKCS7.java (1096 => 1097)
--- trunk/jopenssl/src/java/org/jruby/ext/openssl/PKCS7.java 2008-08-08 10:54:33 UTC (rev 1096)
+++ trunk/jopenssl/src/java/org/jruby/ext/openssl/PKCS7.java 2008-08-08 10:54:37 UTC (rev 1097)
@@ -27,11 +27,13 @@
***** END LICENSE BLOCK *****/
package org.jruby.ext.openssl;
+
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringWriter;
+import java.security.GeneralSecurityException;
import java.security.PrivateKey;
-import java.security.GeneralSecurityException;
import java.security.cert.CertStore;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
@@ -39,20 +41,20 @@
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-
+import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.cms.ContentInfo;
+import org.bouncycastle.asn1.x509.TBSCertificateStructure;
import org.bouncycastle.cms.CMSEnvelopedData;
import org.bouncycastle.cms.CMSEnvelopedDataGenerator;
+import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
-import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.RecipientInformation;
import org.bouncycastle.cms.SignerInformation;
import org.bouncycastle.cms.SignerInformationStore;
-import org.bouncycastle.asn1.x509.TBSCertificateStructure;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyClass;
@@ -60,15 +62,19 @@
import org.jruby.RubyNumeric;
import org.jruby.RubyObject;
import org.jruby.RubyString;
+import org.jruby.anno.JRubyMethod;
+import org.jruby.exceptions.RaiseException;
+import org.jruby.ext.openssl.impl.BIO;
+import org.jruby.ext.openssl.impl.Mime;
+import org.jruby.ext.openssl.impl.SMIME;
import org.jruby.ext.openssl.x509store.PEMInputOutput;
+import org.jruby.ext.openssl.x509store.StoreContext;
import org.jruby.ext.openssl.x509store.X509AuxCertificate;
-import org.jruby.ext.openssl.x509store.StoreContext;
-import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.builtin.IRubyObject;
-import javax.security.auth.x500.X500Principal;
+import org.jruby.util.ByteList;
/**
* @author <a href="" PROTECTED]">Ola Bini</a>
@@ -105,11 +111,34 @@
mPKCS7.setConstant("NOATTR",runtime.newFixnum(256));
mPKCS7.setConstant("NOSMIMECAP",runtime.newFixnum(512));
}
+
+ public static BIO obj2bio(IRubyObject obj) {
+ return null;
+ }
+
+ public static PKCS7 wrap(RubyClass klass, org.jruby.ext.openssl.impl.PKCS7 p7) {
+ PKCS7 wrapped = new PKCS7(klass.getRuntime(), klass);
+ wrapped.p7 = p7;
+ return wrapped;
+ }
+
+ public static IRubyObject membio2str(Ruby runtime, BIO bio) {
+ return null;
+ }
+
public static class ModuleMethods {
@JRubyMethod(meta=true)
- public static IRubyObject read_smime(IRubyObject recv, IRubyObject arg) {
- System.err.println("WARNING: un-implemented method called PKCS7#read_smime");
- return recv.getRuntime().getNil();
+ public static IRubyObject read_smime(IRubyObject klass, IRubyObject arg) throws IOException {
+ BIO in = obj2bio(arg);
+ BIO[] out = new BIO[]{null};
+ org.jruby.ext.openssl.impl.PKCS7 pkcs7 = new SMIME(Mime.DEFAULT).readPKCS7(in, out);
+ if(pkcs7 == null) {
+ throw new RaiseException(klass.getRuntime(), ((RubyModule)(((RubyModule)klass.getRuntime().getModule("OpenSSL")).getConstant("PKCS7"))).getClass("PKCS7Error"), null, false);
+ }
+ IRubyObject data = "" != null ? membio2str(klass.getRuntime(), out[0]) : klass.getRuntime().getNil();
+ PKCS7 ret = wrap(((RubyModule)(((RubyModule)klass.getRuntime().getModule("OpenSSL")).getConstant("PKCS7"))).getClass("PKCS7"), pkcs7);
+ ret.setData(data);
+ return ret;
}
@JRubyMethod(meta=true, rest=true)
@@ -124,21 +153,94 @@
return recv.getRuntime().getNil();
}
+ private static List<X509Certificate> x509_ary2sk(IRubyObject ary) {
+ List<X509Certificate> certs = new ArrayList<X509Certificate>();
+ RubyArray arr = (RubyArray)ary;
+ for(int i = 0; i<arr.size(); i++) {
+ certs.add(((X509Cert)arr.eltInternal(i)).getAuxCert());
+ }
+ return certs;
+ }
+
/** ossl_pkcs7_s_encrypt
*
*/
@JRubyMethod(meta=true, rest=true)
public static IRubyObject encrypt(IRubyObject recv, IRubyObject[] args) throws Exception {
- System.err.println("WARNING: un-implemented method called PKCS7#encrypt");
- return recv.getRuntime().getNil();
+ IRubyObject certs, data, cipher = recv.getRuntime().getNil(), flags = recv.getRuntime().getNil();
+ javax.crypto.Cipher ciph = null;
+ switch(Arity.checkArgumentCount(recv.getRuntime(), args, 2, 4)) {
+ case 4:
+ flags = args[3];
+ case 3:
+ cipher = args[2];
+ }
+ data = ""
+ certs = args[0];
+
+ if(cipher.isNil()) {
+ ciph = javax.crypto.Cipher.getInstance("RC2/CBC/PKCS5Padding");
+ } else {
+ ciph = ((Cipher)cipher).getCipher();
+ }
+
+ int flg = flags.isNil() ? 0 : RubyNumeric.fix2int(flags);
+ byte[] in = data.convertToString().getBytes();
+ List<X509Certificate> x509s = x509_ary2sk(certs);
+ org.jruby.ext.openssl.impl.PKCS7 p7 = org.jruby.ext.openssl.impl.PKCS7.encrypt(x509s, in, ciph, flg);
+ PKCS7 ret = wrap(((RubyModule)(((RubyModule)recv.getRuntime().getModule("OpenSSL")).getConstant("PKCS7"))).getClass("PKCS7"), p7);
+ ret.setData(data);
+
+ return ret;
}
}
+
public PKCS7(Ruby runtime, RubyClass type) {
super(runtime,type);
}
+ private org.jruby.ext.openssl.impl.PKCS7 p7;
+
+ public void setData(IRubyObject object) {
+ setInstanceVariable("@data", object);
+ }
+
+ public IRubyObject getData() {
+ return getInstanceVariable("@data");
+ }
+
@JRubyMethod(name="initialize", rest=true)
public IRubyObject _initialize(IRubyObject[] args) throws Exception {
+ IRubyObject arg = null;
+ if(Arity.checkArgumentCount(getRuntime(), args, 0, 1) == 0) {
+ return this;
+ }
+ arg = args[0];
+
+ arg = OpenSSLImpl.to_der_if_possible(arg);
+
+
+// PKCS7 *p7;
+// BIO *in;
+// VALUE arg;
+
+// if(rb_scan_args(argc, argv, "01", &arg) == 0)
+// return self;
+// arg = ossl_to_der_if_possible(arg);
+// in = ossl_obj2bio(arg);
+// p7 = PEM_read_bio_PKCS7(in, (PKCS7 **)&DATA_PTR(self), NULL, NULL);
+// if (!p7) {
+// BIO_reset(in);
+// p7 = d2i_PKCS7_bio(in, (PKCS7 **)&DATA_PTR(self));
+// }
+// BIO_free(in);
+// ossl_pkcs7_set_data(self, Qnil);
+// ossl_pkcs7_set_err_string(self, Qnil);
+
+// return self;
+
+
+
System.err.println("WARNING: un-implemented method called PKCS7#initialize");
return this;
}
@@ -275,9 +377,8 @@
}
@JRubyMethod
- public IRubyObject to_der() throws Exception {
- System.err.println("WARNING: un-implemented method called PKCS7#to_der");
- return getRuntime().getNil();
+ public IRubyObject to_der() throws IOException {
+ return getRuntime().newString(new ByteList(p7.toASN1(), false));
}
public static class SignerInfo extends RubyObject {
Modified: trunk/jopenssl/src/java/org/jruby/ext/openssl/impl/BIO.java (1096 => 1097)
--- trunk/jopenssl/src/java/org/jruby/ext/openssl/impl/BIO.java 2008-08-08 10:54:33 UTC (rev 1096)
+++ trunk/jopenssl/src/java/org/jruby/ext/openssl/impl/BIO.java 2008-08-08 10:54:37 UTC (rev 1097)
@@ -166,6 +166,7 @@
*
*/
public static BIO memBuf(byte[] arr) {
+ // TODO: create real readonly version of MemBIO.
try {
BIO bio = new MemBIO();
bio.write(arr, 0, arr.length);
Modified: trunk/jopenssl/src/java/org/jruby/ext/openssl/impl/PKCS7.java (1096 => 1097)
--- trunk/jopenssl/src/java/org/jruby/ext/openssl/impl/PKCS7.java 2008-08-08 10:54:33 UTC (rev 1096)
+++ trunk/jopenssl/src/java/org/jruby/ext/openssl/impl/PKCS7.java 2008-08-08 10:54:37 UTC (rev 1097)
@@ -34,6 +34,7 @@
import java.security.Signature;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.List;
import java.util.Set;
@@ -43,6 +44,7 @@
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.ASN1Encodable;
+import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
@@ -51,6 +53,7 @@
import org.bouncycastle.asn1.DERObject;
import org.bouncycastle.asn1.DERObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERTaggedObject;
import org.bouncycastle.asn1.DERUTCTime;
import org.bouncycastle.asn1.pkcs.Attribute;
@@ -132,6 +135,20 @@
return fromASN1(ais.readObject());
}
+ protected ASN1Encodable asASN1() {
+ ASN1EncodableVector vector = new ASN1EncodableVector();
+ DERObjectIdentifier contentType = ASN1Registry.nid2obj(getType());
+ vector.add(contentType);
+ return new DERSequence(vector);
+ }
+
+ /* c: i2d_PKCS7
+ *
+ */
+ public byte[] toASN1() throws IOException {
+ return asASN1().getEncoded();
+ }
+
/* c: PKCS7_encrypt
*
*/
@@ -259,7 +276,33 @@
private final static int EVP_MAX_IV_LENGTH = 16;
private final static int EVP_MAX_BLOCK_LENGTH = 32;
+ private final static byte[] PEM_STRING_PKCS7_START = "-----BEGIN PKCS7-----".getBytes();
+ /** c: PEM_read_bio_PKCS7
+ *
+ */
+ public static PKCS7 readPEM(BIO input) {
+ try {
+ byte[] buffer = new byte[SMIME.MAX_SMLEN];
+ int read = -1;
+ read = input.gets(buffer, SMIME.MAX_SMLEN);
+ if(read > PEM_STRING_PKCS7_START.length) {
+ byte[] tmp = new byte[PEM_STRING_PKCS7_START.length];
+ System.arraycopy(buffer, 0, tmp, 0, tmp.length);
+ if(Arrays.equals(PEM_STRING_PKCS7_START, tmp)) {
+ return fromASN1(BIO.base64Filter(input));
+ } else {
+ /// TODO: err
+ return null;
+ }
+ } else {
+ return null;
+ }
+ } catch(IOException e) {
+ throw new PKCS7Exception(F_SMIME_READ_PKCS7, -1, e.toString());
+ }
+ }
+
/** c: stati PKCS7_bio_add_digest
*
*/
@@ -358,8 +401,13 @@
int klen = -1;
+ String algoBase = evpCipher.getAlgorithm();
+ if(algoBase.indexOf('/') != -1) {
+ algoBase = algoBase.split("/")[0];
+ }
+
try {
- KeyGenerator gen = KeyGenerator.getInstance(evpCipher.getAlgorithm());
+ KeyGenerator gen = KeyGenerator.getInstance(algoBase);
gen.init(new SecureRandom());
SecretKey key = gen.generateKey();
klen = ((SecretKeySpec)key).getEncoded().length*8;
Modified: trunk/jopenssl/test/openssl/test_pkcs7.rb (1096 => 1097)
--- trunk/jopenssl/test/openssl/test_pkcs7.rb 2008-08-08 10:54:33 UTC (rev 1096)
+++ trunk/jopenssl/test/openssl/test_pkcs7.rb 2008-08-08 10:54:37 UTC (rev 1097)
@@ -1,3 +1,8 @@
+if defined?(JRUBY_VERSION)
+ require "java"
+ $CLASSPATH << 'pkg/classes'
+ $CLASSPATH << 'lib/bcprov-jdk14-139.jar'
+end
begin
require "openssl"
require File.join(File.dirname(__FILE__), "utils.rb")
Modified: trunk/jopenssl/test/test_java_pkcs7.rb (1096 => 1097)
--- trunk/jopenssl/test/test_java_pkcs7.rb 2008-08-08 10:54:33 UTC (rev 1096)
+++ trunk/jopenssl/test/test_java_pkcs7.rb 2008-08-08 10:54:37 UTC (rev 1097)
@@ -692,11 +692,78 @@
certs = [X509Cert]
cipher = Cipher.get_instance("AES", BCP.new)
data = ""
- puts
- puts PKCS7::encrypt(certs, data, cipher, PKCS7::BINARY)
- puts
- puts EXISTING_PKCS7_1
+ PKCS7::encrypt(certs, data, cipher, PKCS7::BINARY)
+# puts
+# puts PKCS7::encrypt(certs, data, cipher, PKCS7::BINARY)
+# puts
+# puts EXISTING_PKCS7_1
end
+
+ EXISTING_PKCS7_PEM = <<PKCS7STR
+-----BEGIN PKCS7-----
+MIICIAYJKoZIhvcNAQcDoIICETCCAg0CAQAxggG4MIHZAgEAMEIwPTETMBEGCgmS
+JomT8ixkARkWA29yZzEZMBcGCgmSJomT8ixkARkWCXJ1YnktbGFuZzELMAkGA1UE
+AwwCQ0ECAQIwDQYJKoZIhvcNAQEBBQAEgYCPGMV4KS/8amYA2xeIjj9qLseJf7dl
+BtSDp+YAU3y1JnW7XufBCKxYw7eCuhWWA/mrxijr+wdsFDvSalM6nPX2P2NiVMWP
+a7mzErZ4WrzkKIuGczYPYPJetwBYuhik3ya4ygYygoYssVRAITOSsEKpfqHAPmI+
+AUJkqmCdGpQu9TCB2QIBADBCMD0xEzARBgoJkiaJk/IsZAEZFgNvcmcxGTAXBgoJ
+kiaJk/IsZAEZFglydWJ5LWxhbmcxCzAJBgNVBAMMAkNBAgEDMA0GCSqGSIb3DQEB
+AQUABIGAPaBX0KM3S+2jcrQrncu1jrvm1PUXlUvMfFIG2oBfPkMhiqCBvkOct1Ve
+ws1hxvGtsqyjAUn02Yx1+gQJhTN4JZZHNqkfi0TwN32nlwLxclKcrbF9bvtMiVHx
+V3LrSygblxxJsBf8reoV4yTJRa3w98bEoDhjUwjfy5xTml2cAn4wTAYJKoZIhvcN
+AQcBMB0GCWCGSAFlAwQBAgQQath+2gUo4ntkKl8FO1LLhoAg58j0Jn/OfWG3rNRH
+kTtUQfnBFk/UGbTZgExHILaGz8Y=
+-----END PKCS7-----
+PKCS7STR
+
+ PKCS7_PEM_CONTENTS = "\347\310\364&\177\316}a\267\254\324G\221;TA\371\301\026O\324\031\264\331\200LG \266\206\317\306"
+
+ PKCS7_PEM_FIRST_KEY = "\217\030\305x)/\374jf\000\333\027\210\216?j.\307\211\177\267e\006\324\203\247\346\000S|\265&u\273^\347\301\b\254X\303\267\202\272\025\226\003\371\253\306(\353\373\al\024;\322jS:\234\365\366?cbT\305\217k\271\263\022\266xZ\274\344(\213\206s6\017`\362^\267\000X\272\030\244\337&\270\312\0062\202\206,[EMAIL PROTECTED]>b>\001Bd\252`\235\032\224.\365"
+
+ PKCS7_PEM_SECOND_KEY = "=\240W\320\2437K\355\243r\264+\235\313\265\216\273\346\324\365\027\225K\314|R\006\332\200_>C!\212\240\201\276C\234\267U^\302\315a\306\361\255\262\254\243\001I\364\331\214u\372\004\t\2053x%\226G6\251\037\213D\3607}\247\227\002\361rR\234\255\261}n\373L\211Q\361Wr\353K(\e\227\034I\260\027\374\255\352\025\343$\311E\255\360\367\306\304\2408cS\b\337\313\234S\232]\234\002~"
+
+ def test_PEM_read_pkcs7_bio
+ bio = BIO::mem_buf(EXISTING_PKCS7_PEM.to_java_bytes)
+ p7 = PKCS7.read_pem(bio)
+
+ assert_equal ASN1Registry::NID_pkcs7_enveloped, p7.type
+ env = p7.get_enveloped
+ assert_equal 0, env.version
+ enc_data = env.enc_data
+ assert_equal ASN1Registry::NID_pkcs7_data, enc_data.content_type
+ assert_equal ASN1Registry::NID_aes_128_cbc, ASN1Registry::obj2nid(enc_data.algorithm.get_object_id)
+ assert_equal PKCS7_PEM_CONTENTS, String.from_java_bytes(enc_data.enc_data.octets)
+
+ ris = env.recipient_info
+ assert_equal 2, ris.size
+
+ first = second = nil
+ tmp = ris.iterator.next
+
+ if tmp.issuer_and_serial.certificate_serial_number.value == 2
+ first = tmp
+ iter = ris.iterator
+ iter.next
+ second = iter.next
+ else
+ second = tmp
+ iter = ris.iterator
+ iter.next
+ first = iter.next
+ end
+
+ assert_equal 0, first.version
+ assert_equal 0, second.version
+
+ assert_equal "DC=org,DC=ruby-lang,CN=CA", first.issuer_and_serial.name.to_s
+ assert_equal "DC=org,DC=ruby-lang,CN=CA", second.issuer_and_serial.name.to_s
+
+ assert_equal ASN1Registry::NID_rsaEncryption, ASN1Registry::obj2nid(first.key_enc_algor.get_object_id)
+ assert_equal ASN1Registry::NID_rsaEncryption, ASN1Registry::obj2nid(second.key_enc_algor.get_object_id)
+
+ assert_equal PKCS7_PEM_FIRST_KEY, String.from_java_bytes(first.enc_key.octets)
+ assert_equal PKCS7_PEM_SECOND_KEY, String.from_java_bytes(second.enc_key.octets)
+ end
end
end