Title: [1097] trunk/jopenssl: Make reading of PEM stuff work fine

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
 
_______________________________________________
Jruby-extras-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/jruby-extras-devel

Reply via email to