Home » geronimo-2.2-source-release » org.apache.geronimo.crypto.jce » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package org.apache.geronimo.crypto.jce;
   19   
   20   import java.io.ByteArrayInputStream;
   21   import java.io.ByteArrayOutputStream;
   22   import java.io.IOException;
   23   import java.security.InvalidKeyException;
   24   import java.security.KeyFactory;
   25   import java.security.NoSuchAlgorithmException;
   26   import java.security.NoSuchProviderException;
   27   import java.security.PrivateKey;
   28   import java.security.PublicKey;
   29   import java.security.Signature;
   30   import java.security.SignatureException;
   31   import java.security.spec.InvalidKeySpecException;
   32   import java.security.spec.X509EncodedKeySpec;
   33   import java.util.Hashtable;
   34   
   35   import javax.security.auth.x500.X500Principal;
   36   
   37   import org.apache.geronimo.crypto.asn1.ASN1InputStream;
   38   import org.apache.geronimo.crypto.asn1.ASN1Sequence;
   39   import org.apache.geronimo.crypto.asn1.ASN1Set;
   40   import org.apache.geronimo.crypto.asn1.DERBitString;
   41   import org.apache.geronimo.crypto.asn1.DERObjectIdentifier;
   42   import org.apache.geronimo.crypto.asn1.DEROutputStream;
   43   import org.apache.geronimo.crypto.asn1.pkcs.PKCSObjectIdentifiers;
   44   import org.apache.geronimo.crypto.asn1.pkcs.CertificationRequest;
   45   import org.apache.geronimo.crypto.asn1.pkcs.CertificationRequestInfo;
   46   import org.apache.geronimo.crypto.asn1.x509.AlgorithmIdentifier;
   47   import org.apache.geronimo.crypto.asn1.x509.SubjectPublicKeyInfo;
   48   import org.apache.geronimo.crypto.asn1.x509.X509Name;
   49   import org.apache.geronimo.crypto.asn1.x9.X9ObjectIdentifiers;
   50   
   51   /**
   52    * A class for verifying and creating PKCS10 Certification requests.
   53    * <pre>
   54    * CertificationRequest ::= SEQUENCE {
   55    *   certificationRequestInfo  CertificationRequestInfo,
   56    *   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
   57    *   signature                 BIT STRING
   58    * }
   59    *
   60    * CertificationRequestInfo ::= SEQUENCE {
   61    *   version             INTEGER { v1(0) } (v1,...),
   62    *   subject             Name,
   63    *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
   64    *   attributes          [0] Attributes{{ CRIAttributes }}
   65    *  }
   66    *
   67    *  Attributes { ATTRIBUTE:IOSet } ::= SET OF Attribute{{ IOSet }}
   68    *
   69    *  Attribute { ATTRIBUTE:IOSet } ::= SEQUENCE {
   70    *    type    ATTRIBUTE.&id({IOSet}),
   71    *    values  SET SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
   72    *  }
   73    * </pre>
   74    */
   75   public class PKCS10CertificationRequest
   76       extends CertificationRequest
   77   {
   78       private static Hashtable            algorithms = new Hashtable();
   79       private static Hashtable            oids = new Hashtable();
   80   
   81       static
   82       {
   83           algorithms.put("MD2WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
   84           algorithms.put("MD2WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.2"));
   85           algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.1"));
   86           algorithms.put("MD5WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
   87           algorithms.put("MD5WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
   88           algorithms.put("RSAWITHMD5", new DERObjectIdentifier("1.2.840.113549.1.1.4"));
   89           algorithms.put("SHA1WITHRSAENCRYPTION", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
   90           algorithms.put("SHA1WITHRSA", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
   91           algorithms.put("SHA224WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha224WithRSAEncryption);
   92           algorithms.put("SHA224WITHRSA", PKCSObjectIdentifiers.sha224WithRSAEncryption);
   93           algorithms.put("SHA256WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha256WithRSAEncryption);
   94           algorithms.put("SHA256WITHRSA", PKCSObjectIdentifiers.sha256WithRSAEncryption);
   95           algorithms.put("SHA384WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha384WithRSAEncryption);
   96           algorithms.put("SHA384WITHRSA", PKCSObjectIdentifiers.sha384WithRSAEncryption);
   97           algorithms.put("SHA512WITHRSAENCRYPTION", PKCSObjectIdentifiers.sha512WithRSAEncryption);
   98           algorithms.put("SHA512WITHRSA", PKCSObjectIdentifiers.sha512WithRSAEncryption);
   99           algorithms.put("RSAWITHSHA1", new DERObjectIdentifier("1.2.840.113549.1.1.5"));
  100           algorithms.put("RIPEMD160WITHRSAENCRYPTION", new DERObjectIdentifier("1.3.36.3.3.1.2"));
  101           algorithms.put("RIPEMD160WITHRSA", new DERObjectIdentifier("1.3.36.3.3.1.2"));
  102           algorithms.put("SHA1WITHDSA", new DERObjectIdentifier("1.2.840.10040.4.3"));
  103           algorithms.put("DSAWITHSHA1", new DERObjectIdentifier("1.2.840.10040.4.3"));
  104           algorithms.put("SHA1WITHECDSA", X9ObjectIdentifiers.ecdsa_with_SHA1);
  105           algorithms.put("ECDSAWITHSHA1", X9ObjectIdentifiers.ecdsa_with_SHA1);
  106   
  107           //
  108           // reverse mappings
  109           //
  110           oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA");
  111           oids.put(PKCSObjectIdentifiers.sha224WithRSAEncryption, "SHA224WITHRSA");
  112           oids.put(PKCSObjectIdentifiers.sha256WithRSAEncryption, "SHA256WITHRSA");
  113           oids.put(PKCSObjectIdentifiers.sha384WithRSAEncryption, "SHA384WITHRSA");
  114           oids.put(PKCSObjectIdentifiers.sha512WithRSAEncryption, "SHA512WITHRSA");
  115   
  116           oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
  117           oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
  118           oids.put(new DERObjectIdentifier("1.2.840.113549.1.1.1"), "MD5WIDHRSA");
  119           oids.put(new DERObjectIdentifier("1.2.840.10040.4.3"), "DSAWITHSHA1");
  120           oids.put(X9ObjectIdentifiers.ecdsa_with_SHA1, "DSAWITHSHA1");
  121       }
  122   
  123       private static ASN1Sequence toDERSequence(
  124           byte[]  bytes)
  125       {
  126           try
  127           {
  128               ByteArrayInputStream    bIn = new ByteArrayInputStream(bytes);
  129               ASN1InputStream         dIn = new ASN1InputStream(bIn);
  130   
  131               return (ASN1Sequence)dIn.readObject();
  132           }
  133           catch (Exception e)
  134           {
  135               throw new IllegalArgumentException("badly encoded request", e);
  136           }
  137       }
  138   
  139       /**
  140        * construct a PKCS10 certification request from a DER encoded
  141        * byte stream.
  142        */
  143       public PKCS10CertificationRequest(
  144           byte[]  bytes)
  145       {
  146           super(toDERSequence(bytes));
  147       }
  148   
  149       public PKCS10CertificationRequest(
  150           ASN1Sequence  sequence)
  151       {
  152           super(sequence);
  153       }
  154   
  155       /**
  156        * create a PKCS10 certfication request using the BC provider.
  157        */
  158       public PKCS10CertificationRequest(
  159           String              signatureAlgorithm,
  160           X509Name            subject,
  161           PublicKey           key,
  162           ASN1Set             attributes,
  163           PrivateKey          signingKey)
  164           throws NoSuchAlgorithmException, NoSuchProviderException,
  165                   InvalidKeyException, SignatureException
  166       {
  167           this(signatureAlgorithm, subject, key, attributes, signingKey, null);
  168       }
  169   
  170       private static X509Name convertName(
  171           X500Principal	name)
  172       {
  173           try
  174           {
  175               return new X509Principal(name.getEncoded());
  176           }
  177           catch (IOException e)
  178           {
  179               throw new IllegalArgumentException("can't convert name", e);
  180           }
  181       }
  182   
  183       /**
  184        * create a PKCS10 certfication request using the BC provider.
  185        */
  186       public PKCS10CertificationRequest(
  187           String              signatureAlgorithm,
  188           X500Principal       subject,
  189           PublicKey           key,
  190           ASN1Set             attributes,
  191           PrivateKey          signingKey)
  192           throws NoSuchAlgorithmException, NoSuchProviderException,
  193                   InvalidKeyException, SignatureException
  194       {
  195           this(signatureAlgorithm, convertName(subject), key, attributes, signingKey, null);
  196       }
  197   
  198       /**
  199        * create a PKCS10 certfication request using the named provider.
  200        */
  201       public PKCS10CertificationRequest(
  202           String              signatureAlgorithm,
  203           X500Principal       subject,
  204           PublicKey           key,
  205           ASN1Set             attributes,
  206           PrivateKey          signingKey,
  207           String              provider)
  208           throws NoSuchAlgorithmException, NoSuchProviderException,
  209                   InvalidKeyException, SignatureException
  210       {
  211           this(signatureAlgorithm, convertName(subject), key, attributes, signingKey, provider);
  212       }
  213   
  214       /**
  215        * create a PKCS10 certfication request using the named provider.
  216        */
  217       public PKCS10CertificationRequest(
  218           String              signatureAlgorithm,
  219           X509Name            subject,
  220           PublicKey           key,
  221           ASN1Set             attributes,
  222           PrivateKey          signingKey,
  223           String              provider)
  224           throws NoSuchAlgorithmException, NoSuchProviderException,
  225                   InvalidKeyException, SignatureException
  226       {
  227           DERObjectIdentifier sigOID = (DERObjectIdentifier)algorithms.get(signatureAlgorithm.toUpperCase());
  228   
  229           if (sigOID == null)
  230           {
  231               throw new IllegalArgumentException("Unknown signature type requested");
  232           }
  233   
  234           if (subject == null)
  235           {
  236               throw new IllegalArgumentException("subject must not be null");
  237           }
  238   
  239           if (key == null)
  240           {
  241               throw new IllegalArgumentException("public key must not be null");
  242           }
  243   
  244           this.sigAlgId = new AlgorithmIdentifier(sigOID, null);
  245   
  246           byte[]                  bytes = key.getEncoded();
  247           ByteArrayInputStream    bIn = new ByteArrayInputStream(bytes);
  248           ASN1InputStream         dIn = new ASN1InputStream(bIn);
  249   
  250           try
  251           {
  252               this.reqInfo = new CertificationRequestInfo(subject, new SubjectPublicKeyInfo((ASN1Sequence)dIn.readObject()), attributes);
  253           }
  254           catch (IOException e)
  255           {
  256               throw new IllegalArgumentException("can't encode public key", e);
  257           }
  258   
  259           Signature sig = null;
  260   
  261           try
  262           {
  263               if (provider == null) {
  264                   sig = Signature.getInstance(sigAlgId.getObjectId().getId());
  265               }
  266               else {
  267                   sig = Signature.getInstance(sigAlgId.getObjectId().getId(), provider);
  268               }
  269           }
  270           catch (NoSuchAlgorithmException e)
  271           {
  272               if (provider == null) {
  273                   sig = Signature.getInstance(signatureAlgorithm);
  274               }
  275               else {
  276                   sig = Signature.getInstance(signatureAlgorithm, provider);
  277               }
  278           }
  279   
  280           sig.initSign(signingKey);
  281   
  282           try
  283           {
  284               ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
  285               DEROutputStream         dOut = new DEROutputStream(bOut);
  286   
  287               dOut.writeObject(reqInfo);
  288   
  289               sig.update(bOut.toByteArray());
  290           }
  291           catch (Exception e)
  292           {
  293               throw new SecurityException("exception encoding TBS cert request - " + e.getMessage(), e);
  294           }
  295   
  296           this.sigBits = new DERBitString(sig.sign());
  297       }
  298   
  299       /**
  300        * return the public key associated with the certification request -
  301        * the public key is created using the BC provider.
  302        */
  303       public PublicKey getPublicKey()
  304           throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeyException
  305       {
  306           return getPublicKey(null);
  307       }
  308   
  309       public PublicKey getPublicKey(
  310           String  provider)
  311           throws NoSuchAlgorithmException, NoSuchProviderException,
  312                   InvalidKeyException
  313       {
  314           SubjectPublicKeyInfo    subjectPKInfo = reqInfo.getSubjectPublicKeyInfo();
  315   
  316           try
  317           {
  318               X509EncodedKeySpec      xspec = new X509EncodedKeySpec(new DERBitString(subjectPKInfo).getBytes());
  319               AlgorithmIdentifier     keyAlg = subjectPKInfo.getAlgorithmId ();
  320               try {
  321   
  322                   if (provider == null) {
  323                       return KeyFactory.getInstance(keyAlg.getObjectId().getId ()).generatePublic(xspec);
  324                   }
  325                   else {
  326                       return KeyFactory.getInstance(keyAlg.getObjectId().getId (), provider).generatePublic(xspec);
  327                   }
  328   
  329               } catch (NoSuchAlgorithmException e) {
  330                   // if we can't resolve this via the OID, just as for the RSA algorithm.  This is all
  331                   // Geronimo requires anyway.
  332                   if (provider == null) {
  333                       return KeyFactory.getInstance("RSA").generatePublic(xspec);
  334                   }
  335                   else {
  336                       return KeyFactory.getInstance("RSA", provider).generatePublic(xspec);
  337                   }
  338               }
  339           }
  340           catch (InvalidKeySpecException e)
  341           {
  342               throw (InvalidKeyException)new InvalidKeyException("error decoding public key").initCause(e);
  343           }
  344       }
  345   
  346       /**
  347        * verify the request using the BC provider.
  348        */
  349       public boolean verify()
  350           throws NoSuchAlgorithmException, NoSuchProviderException,
  351                   InvalidKeyException, SignatureException
  352       {
  353           return verify(null);
  354       }
  355   
  356       public boolean verify(
  357           String provider)
  358           throws NoSuchAlgorithmException, NoSuchProviderException,
  359                   InvalidKeyException, SignatureException
  360       {
  361           Signature   sig = null;
  362   
  363           try
  364           {
  365               if (provider == null) {
  366                   sig = Signature.getInstance(sigAlgId.getObjectId().getId());
  367               }
  368               else {
  369                   sig = Signature.getInstance(sigAlgId.getObjectId().getId(), provider);
  370               }
  371           }
  372           catch (NoSuchAlgorithmException e)
  373           {
  374               //
  375               // try an alternate
  376               //
  377               if (oids.get(sigAlgId.getObjectId().getId()) != null)
  378               {
  379                   String  signatureAlgorithm = (String)oids.get(sigAlgId.getObjectId().getId());
  380   
  381                   if (provider == null) {
  382                       sig = Signature.getInstance(signatureAlgorithm);
  383                   }
  384                   else {
  385                       sig = Signature.getInstance(signatureAlgorithm, provider);
  386                   }
  387               }
  388           }
  389   
  390           sig.initVerify(this.getPublicKey(provider));
  391   
  392           try
  393           {
  394               ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
  395               DEROutputStream         dOut = new DEROutputStream(bOut);
  396   
  397               dOut.writeObject(reqInfo);
  398   
  399               sig.update(bOut.toByteArray());
  400           }
  401           catch (Exception e)
  402           {
  403               throw (SecurityException)new SecurityException("exception encoding TBS cert request - " + e.getMessage()).initCause(e);
  404           }
  405   
  406           return sig.verify(sigBits.getBytes());
  407       }
  408   
  409       /**
  410        * return a DER encoded byte array representing this object
  411        */
  412       public byte[] getEncoded()
  413       {
  414           ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
  415           DEROutputStream         dOut = new DEROutputStream(bOut);
  416   
  417           try
  418           {
  419               dOut.writeObject(this);
  420           }
  421           catch (IOException e)
  422           {
  423               throw new RuntimeException(e.getMessage(), e);
  424           }
  425   
  426           return bOut.toByteArray();
  427       }
  428   }

Home » geronimo-2.2-source-release » org.apache.geronimo.crypto.jce » [javadoc | source]