Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
BEGIN LICENSE BLOCK ***** Version: CPL 1.0/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Common Public License Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.eclipse.org/legal/cpl-v10.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. Copyright (C) 2006, 2007 Ola Bini <ola@ologix.com> Alternatively, the contents of this file may be used under the terms of either of the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the CPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the CPL, the GPL or the LGPL. END LICENSE BLOCK ***
 
 package org.jruby.ext.openssl;
 
 import java.util.List;
 import java.util.Set;
 
 import  org.bouncycastle.asn1.ASN1EncodableVector;
 import  org.bouncycastle.asn1.ASN1InputStream;
 import  org.bouncycastle.asn1.DERObjectIdentifier;
 import  org.bouncycastle.asn1.DERSequence;
 import  org.bouncycastle.asn1.x509.GeneralName;
 import  org.bouncycastle.asn1.x509.GeneralNames;
 import  org.bouncycastle.x509.X509V3CertificateGenerator;
 import org.jruby.Ruby;

Author(s):
Ola Bini
 
 @SuppressWarnings("deprecation")
 public class X509Cert extends RubyObject {
     private static final long serialVersionUID = 5626619026058595493L;
 
     private static ObjectAllocator X509CERT_ALLOCATOR = new ObjectAllocator() {
         public IRubyObject allocate(Ruby runtimeRubyClass klass) {
             return new X509Cert(runtimeklass);
         }
     };
 
     public static void createX509Cert(Ruby runtimeRubyModule mX509) {
         RubyClass cX509Cert = mX509.defineClassUnder("Certificate",runtime.getObject(),);
         RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError");
         mX509.defineClassUnder("CertificateError",openSSLError,openSSLError.getAllocator());
 
         cX509Cert.defineAnnotatedMethods(X509Cert.class);
     }
 
     public X509Cert(Ruby runtimeRubyClass type) {
         super(runtime,type);
     }
    private IRubyObject serial;
    private IRubyObject not_before;
    private IRubyObject not_after;
    private IRubyObject issuer;
    private IRubyObject subject;
    private IRubyObject public_key;
    private IRubyObject sig_alg;
    private IRubyObject version;
    private List<IRubyObjectextensions;
    private boolean changed = true;
    private X509V3CertificateGenerator generator = new X509V3CertificateGenerator();
    private X509Certificate cert;
    private String public_key_algorithm;
    private byte[] public_key_encoded;
        if(null == ) {
            return null;
        }
        if( instanceof X509AuxCertificate) {
            return (X509AuxCertificate);
        }
        return new X509AuxCertificate();
    }
    public static IRubyObject wrap(Ruby runtimeCertificate cthrows CertificateEncodingException {
        RubyClass cr = Utils.getClassFromPath(runtime"OpenSSL::X509::Certificate");
        return cr.callMethod(runtime.getCurrentContext(), "new", RubyString.newString(runtimec.getEncoded()));
    }
    // this is the javax.security counterpart of the previous wrap method
        RubyClass cr = Utils.getClassFromPath(runtime"OpenSSL::X509::Certificate");
        return cr.callMethod(runtime.getCurrentContext(), "new", RubyString.newString(runtimec.getEncoded()));
    }
    @JRubyMethod(name="initialize", optional = 1, frame=true)
    public IRubyObject initialize(ThreadContext contextIRubyObject[] argsBlock unusedBlock) {
        Ruby runtime = context.runtime;
         = new ArrayList<IRubyObject>();
        if(args.length == 0) {
            return this;
        }
        byte[] bytes = OpenSSLImpl.readX509PEM(args[0]);
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        
        CertificateFactory cf;
        RubyModule ossl = runtime.getModule("OpenSSL");
        RubyModule x509 = (RubyModule)ossl.getConstant("X509");
        IRubyObject x509Name = x509.getConstant("Name");
        try {
            cf = CertificateFactory.getInstance("X.509");
             = (X509Certificate)cf.generateCertificate(bis);
        } catch (CertificateException ex) {
            throw newCertificateError(runtimeex);
        }
        if ( == null) {
            throw newCertificateError(runtime, (Stringnull);
        }
        set_serial(RubyNumeric.str2inum(runtime,runtime.newString(.getSerialNumber().toString()),10));
        set_not_before(RubyTime.newTime(runtime,.getNotBefore().getTime()));
        set_not_after(RubyTime.newTime(runtime,.getNotAfter().getTime()));
        set_subject(x509Name.callMethod(context,"new",RubyString.newString(runtime.getSubjectX500Principal().getEncoded())));
        set_issuer(x509Name.callMethod(context,"new",RubyString.newString(runtime.getIssuerX500Principal().getEncoded())));
        String algorithm = .getPublicKey().getAlgorithm();
        set_public_key(algorithm.getPublicKey().getEncoded());
        IRubyObject extFact = ((RubyClass)(x509.getConstant("ExtensionFactory"))).callMethod(context,"new");
        extFact.callMethod(context,"subject_certificate=",this);
        Set<Stringcrit = .getCriticalExtensionOIDs();
        if (crit != null) {
            for (Iterator<Stringiter = crit.iterator(); iter.hasNext();) {
                String critOid = iter.next();
                byte[] value = .getExtensionValue(critOid);
                IRubyObject rValue = ASN1.decode(ossl.getConstant("ASN1"), runtime.newString(new ByteList(valuefalse))).callMethod(context"value");
                X509Extensions.Extension ext = (X509Extensions.Extensionx509.getConstant("Extension").callMethod(context"new",
                        new IRubyObject[] { runtime.newString(critOid), rValueruntime.getTrue() });
                add_extension(ext);
            }
        }
        Set<Stringncrit = .getNonCriticalExtensionOIDs();
        if (ncrit != null) {
            for (Iterator<Stringiter = ncrit.iterator(); iter.hasNext();) {
                String ncritOid = iter.next();
                byte[] value = .getExtensionValue(ncritOid);
                // TODO: wired. J9 returns null for an OID given in getNonCriticalExtensionOIDs()
                if (value != null) {
                    IRubyObject rValue = ASN1.decode(ossl.getConstant("ASN1"), runtime.newString(new ByteList(valuefalse))).callMethod(context"value");
                    X509Extensions.Extension ext = (X509Extensions.Extensionx509.getConstant("Extension").callMethod(context"new",
                            new IRubyObject[] { runtime.newString(ncritOid), rValueruntime.getFalse() });
                    add_extension(ext);
                }
            }
        }
         = false;
        return this;
    }
    //Lazy method for public key instantiation
    private void set_public_key(String algorithmbyte[] encoded) {
        this. = algorithm;
        this. = encoded;
    }
    public static RaiseException newCertificateError(Ruby runtimeException ex) {
        return newCertificateError(runtimeex.getMessage());
    }
    public static RaiseException newCertificateError(Ruby runtimeString message) {
        throw Utils.newError(runtime"OpenSSL::X509::CertificateError"message);
    }
    @Override
    public IRubyObject initialize_copy(IRubyObject obj) {
        if(this == obj) {
            return this;
        }
        checkFrozen();
        return this;
    }
    public IRubyObject to_der() {
        try {
            return RubyString.newString(getRuntime(), .getEncoded());
        } catch (CertificateEncodingException ex) {
            throw newCertificateError(getRuntime(), ex);
        }
    }
    @JRubyMethod(name={"to_pem","to_s"})
    public IRubyObject to_pem() {
        try {
            StringWriter w = new StringWriter();
            PEMInputOutput.writeX509Certificate(wgetAuxCert());
            w.close();
            return getRuntime().newString(w.toString());
        } catch (IOException ex) {
            throw getRuntime().newIOErrorFromException(ex);
        }
    }
    public IRubyObject to_text() {
        return getRuntime().newString(getAuxCert().toString());
    }
    @Override
    public IRubyObject inspect() {
        return getRuntime().getNil();
    }
    public IRubyObject version() {
        return ;
    }
    @JRubyMethod(name="version=")
    public IRubyObject set_version(IRubyObject arg) {
        if(!arg.equals(this.)) {
             = true;
        }
        this. = arg;
        return arg;
    }
    public IRubyObject signature_algorithm() {
        return ;
    }
    public IRubyObject serial() {
        return ;
    }
    @JRubyMethod(name="serial=")
    public IRubyObject set_serial(IRubyObject num) {
        if(!num.equals(this.)) {
             = true;
        }
         = num;
        String s = .toString();
        BigInteger bi;
        if (s.equals("0")) { // MRI compatibility: allow 0 serial number
            bi = .;
        } else {
            bi = new BigInteger(s);
        }
        .setSerialNumber(bi);
        return num;
    }
    public IRubyObject subject() {
        return ;
    }
    @JRubyMethod(name="subject=")
    public IRubyObject set_subject(IRubyObject arg) {
        if(!arg.equals(this.)) {
             = true;
        }
         = arg;
        .setSubjectDN(((X509Name)).getRealName());
        return arg;
    }
    public IRubyObject issuer() {
        return ;
    }
    @JRubyMethod(name="issuer=")
    public IRubyObject set_issuer(IRubyObject arg) {
        if(!arg.equals(this.)) {
             = true;
        }
         = arg;
        .setIssuerDN(((X509Name)).getRealName());
        return arg;
    }
    public IRubyObject not_before() {
        return ;
    }
    @JRubyMethod(name="not_before=")
    public IRubyObject set_not_before(IRubyObject arg) {
         = true;
         = arg.callMethod(getRuntime().getCurrentContext(),"getutc");
        ((RubyTime)).setMicroseconds(0);
        .setNotBefore(((RubyTime)).getJavaDate());
        return arg;
    }
    public IRubyObject not_after() {
        return ;
    }
    @JRubyMethod(name="not_after=")
    public IRubyObject set_not_after(IRubyObject arg) {
         = true;
         = arg.callMethod(getRuntime().getCurrentContext(),"getutc");
        ((RubyTime)).setMicroseconds(0);
        .setNotAfter(((RubyTime)).getJavaDate());
        return arg;
    }
    public IRubyObject public_key() {
        if ( == null) {
            lazyInitializePublicKey();
        }
        return .callMethod(getRuntime().getCurrentContext(), "public_key");
    }
    @JRubyMethod(name="public_key=")
    public IRubyObject set_public_key(IRubyObject arg) {
        Utils.checkKind(getRuntime(), arg"OpenSSL::PKey::PKey");
        if(!arg.equals(this.)) {
             = true;
        }
         = arg;
        .setPublicKey(((PKey)).getPublicKey());
        return arg;
    }
    private void lazyInitializePublicKey() {
        if ( == null ||  == null) {
            throw new IllegalStateException("lazy public key initialization failed");
        }
        RubyModule ossl = getRuntime().getModule("OpenSSL");
        RubyModule pkey = (RubyModuleossl.getConstant("PKey");
        ThreadContext tc = getRuntime().getCurrentContext();
        boolean backupChanged = ;
        if ("RSA".equalsIgnoreCase()) {
            set_public_key(pkey.getConstant("RSA").callMethod(tc"new", RubyString.newString(getRuntime(), )));
        } else if ("DSA".equalsIgnoreCase()) {
            set_public_key(pkey.getConstant("DSA").callMethod(tc"new", RubyString.newString(getRuntime(), )));
        } else {
            throw newCertificateError(getRuntime(), "The algorithm " +  + " is unsupported for public keys");
        }
         = backupChanged;
    }
    public IRubyObject sign(ThreadContext contextfinal IRubyObject keyIRubyObject digest) {
        Ruby runtime = context.runtime;
        // Have to obey some artificial constraints of the OpenSSL implementation. Stupid.
        String keyAlg = ((PKey)key).getAlgorithm();
        String digAlg = ((Digest)digest).getShortAlgorithm();
        String digName = ((Digest)digest).name().toString();
        if(("DSA".equalsIgnoreCase(keyAlg) && "MD5".equalsIgnoreCase(digAlg)) ||
           ("RSA".equalsIgnoreCase(keyAlg) && "DSS1".equals(digName))) {
            throw newCertificateError(runtime"signature_algorithm not supported");
        }
        for(Iterator<IRubyObjectiter = .iterator();iter.hasNext();) {
            X509Extensions.Extension ag = (X509Extensions.Extension)iter.next();
            try {
                byte[] bytes = ag.getRealValueBytes();
                .addExtension(ag.getRealOid(),ag.getRealCritical(),bytes);
            } catch (IOException ioe) {
                throw runtime.newIOErrorFromException(ioe);
            }
        }
        .setSignatureAlgorithm(digAlg + "WITH" + keyAlg);
        if ( == null) {
            lazyInitializePublicKey();
        }
        try {
            // X509V3CertificateGenerator depends BC.
            OpenSSLReal.doWithBCProvider(new OpenSSLReal.Runnable() {
                public void run() throws GeneralSecurityException {
                     = .generate(((PKeykey).getPrivateKey(), "BC");
                }
            });
        } catch (GeneralSecurityException gse) {
            throw newCertificateError(getRuntime(), gse.getMessage());
        }
        if ( == null) {
            throw newCertificateError(runtime, (Stringnull);
        }
        String name = ASN1Registry.o2a(.getSigAlgOID());
        if (name == null) {
            name = .getSigAlgOID();
        }
         = runtime.newString(name);
         = false;
        return this;
    }
    public IRubyObject verify(IRubyObject key) {
        if() {
            return getRuntime().getFalse();
        }
        try {
            .verify(((PKey)key).getPublicKey());
            return getRuntime().getTrue();
        } catch (CertificateException ce) {
            throw newCertificateError(getRuntime(), ce);
        } catch (NoSuchAlgorithmException nsae) {
            throw newCertificateError(getRuntime(), nsae);
        } catch (NoSuchProviderException nspe) {
            throw newCertificateError(getRuntime(), nspe);
        } catch (SignatureException se) {
            throw newCertificateError(getRuntime(), se);
        } catch(InvalidKeyException e) {
            return getRuntime().getFalse();
        }
    }
    public IRubyObject check_private_key(IRubyObject arg) {
        PKey key = (PKey)arg;
        PublicKey pkey = key.getPublicKey();
        PublicKey certPubKey = getAuxCert().getPublicKey();
        if (certPubKey.equals(pkey))
            return getRuntime().getTrue();
        return getRuntime().getFalse();
    }
    public IRubyObject extensions() {
        return getRuntime().newArray();
    }
    @SuppressWarnings("unchecked")
    @JRubyMethod(name="extensions=")
    public IRubyObject set_extensions(IRubyObject arg) {
         = new ArrayList<IRubyObject>(((RubyArray)arg).getList());
        return arg;
    }
    public IRubyObject add_extension(IRubyObject arg) {
         = true;
        DERObjectIdentifier oid = ((X509Extensions.Extension)arg).getRealOid();
        if(oid.equals(new DERObjectIdentifier("2.5.29.17"))) {
            boolean one = true;
            for(Iterator<IRubyObjectiter = .iterator();iter.hasNext();) {
                X509Extensions.Extension ag = (X509Extensions.Extension)iter.next();
                if(ag.getRealOid().equals(new DERObjectIdentifier("2.5.29.17"))) {
                    ASN1EncodableVector v1 = new ASN1EncodableVector();
                    try {
                        GeneralName[] n1 = GeneralNames.getInstance(new ASN1InputStream(ag.getRealValueBytes()).readObject()).getNames();
                        GeneralName[] n2 = GeneralNames.getInstance(new ASN1InputStream(((X509Extensions.Extension)arg).getRealValueBytes()).readObject()).getNames();
                        for(int i=0;i<n1.length;i++) {
                            v1.add(n1[i]);
                        }
                        for(int i=0;i<n2.length;i++) {
                            v1.add(n2[i]);
                        }
                    } catch (IOException ex) {
                        throw getRuntime().newIOErrorFromException(ex);
                    }
                    ag.setRealValue(new String(ByteList.plain(new GeneralNames(new DERSequence(v1)).getDEREncoded())));
                    one = false;
                    break;
                }
            }
            if(one) {
                .add(arg);
            }
        } else {
            .add(arg);
        }
        return arg;
    }
}// X509Cert
New to GrepCode? Check out our FAQ X