FileDocCategorySizeDatePackage
Authority.javaAPI DocphoneME MR2 API (J2ME)13016Wed May 02 18:00:40 BST 2007dummyCA

Authority

public class Authority extends Object
This class represents certificate authority.

Fields Summary
private static String
keystoreFilename
Keystore name for CA credentials.
private static String
keystorePassword
Keystore password.
private static String
keyAlias
Alias for CA keys.
private static String
keyPassword
CA key password.
private static String
CASign
Algorithm name for CA signature for new certificates.
private static String[]
algorithms
Signature algorithm attributes - OID, crypto algorithm ID, signature algorithm ID.
private static boolean
init
Is this authority initialized?
private static X509Certificate
CACert
CA certificate.
private static PrivateKey
CAPrivKey
CA private key.
private static long
SerialNumber
Current serial number for new certificate.
private static TLV
CASignatureAlgorithm
TLV structure to be used in new certificates.
private static TLV
CACertPointer
TLV structure to be used for generation of new certificates.
private TLV
CSR
Parsed certificate enrollment request.
private TLV
Certificate
Generated certificate.
private TLV
IssuerAndSerialNumber
Generated IssuerAndSerialNumber data structure.
private String
Status
Current status of CA.
Constructors Summary
Methods Summary
private booleancheckSign()
Verifies signature in certificate enrollment request.

return
true if signature is verified
throws
IOException if IOException occurs
throws
NoSuchAlgorithmException if NoSuchAlgorithmException occurs
throws
InvalidKeySpecException if InvalidKeySpecException occurs
throws
InvalidKeyException if InvalidKeyException occurs
throws
SignatureException if SignatureException occurs


        String algorithmOID = CSR.child.next.child.getOID();
        String cryptoAlg = "";
        String signAlg = "";

        for (int i = 0 ; i < algorithms.length; i++) {
            if (algorithmOID.equals(algorithms[i][0])) {
                cryptoAlg = algorithms[i][1];
                signAlg = algorithms[i][2];
                break;
            }
        }

        byte[] subjectPKInfo = CSR.child.child.next.next.getDERData();
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(subjectPKInfo);
        KeyFactory factory = KeyFactory.getInstance(cryptoAlg);
        PublicKey key = factory.generatePublic(keySpec);

        Signature sig = Signature.getInstance(signAlg);
        sig.initVerify(key);
        sig.update(CSR.child.getDERData());

        byte[] sign = CSR.child.next.next.getValue();
        byte[] signature = new byte[sign.length - 1];
        System.arraycopy(sign, 1, signature, 0, signature.length);
        return sig.verify(signature);
    
private voidcreate()
Creates a new certificate.

throws
NoSuchAlgorithmException if an exception occurs during signature operation
throws
InvalidKeyException if an exception occurs during signature operation
throws
SignatureException if an exception occurs during signature operation


        // Prepare TBSCertificate data structure
        TLV TBSCert = new TLV(TLV.SEQUENCE_TYPE);

        // serial number
        BigInteger serialNumber = BigInteger.valueOf(getSerialNumber());

        TLV current = new TLV(TLV.INTEGER_TYPE, serialNumber.toByteArray());
        TBSCert.child = current;

        // signature algorithm identifier (CA)
        current.next = CASignatureAlgorithm.copy();
        current = current.next;

        // issuer
        current.next = CACertPointer.next.next.next.next.copy();
        current = current.next;

        // validity
        current.next = new TLV(TLV.SEQUENCE_TYPE);
        current = current.next;

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
        current.child = TLV.createUTCTime(calendar);
        calendar.add(Calendar.DAY_OF_MONTH, 30);
        current.child.next = TLV.createUTCTime(calendar);

        // subject
        current.next = CSR.child.child.next.copy();
        current = current.next;

        // subject public key info
        current.next = CSR.child.child.next.next.copy();

        // TBSCertificate is complete, now sign it

        Signature s = Signature.getInstance(CASign);
        s.initSign(CAPrivKey);
        s.update(TBSCert.getDERData());

        byte[] sign1 = s.sign();
        byte[] sign2 = new byte[sign1.length + 1];
        System.arraycopy(sign1, 0, sign2, 1, sign1.length);

        // create Certificate data structure

        Certificate = new TLV(TLV.SEQUENCE_TYPE);

        // TBSCertificate
        Certificate.child = TBSCert;

        // signatureAlgorithm
        current = CASignatureAlgorithm.copy();
        TBSCert.next = current;

        // signatureValue
        current.next = new TLV(TLV.BITSTRING_TYPE, sign2);

        // create IssuerAndSerialNumber data structure

        IssuerAndSerialNumber = new TLV(TLV.SEQUENCE_TYPE);
        IssuerAndSerialNumber.child = CACertPointer.next.next.next.next.copy();
        IssuerAndSerialNumber.child.next = new TLV(TLV.INTEGER_TYPE,
                                               serialNumber.toByteArray());
    
public booleancreateCertificate(byte[] data)
Creates a new certificate.

param
data certificate enrollment request
return
true if a new certificate was generated


                          
        

        if (! init) {
            Status = "Can't load CA credentials.";
            return false;
        }

        try {
            CSR = new TLV(data, 0);
        } catch (Exception e) {
            Status = "Error parsing the CSR.";
            return false;
        }

        try {
            if (! checkSign()) {
                Status = "Signature mismatch.";
                return false;
            }
        } catch (Exception e) {
            Status = "Can't check signature.";
            return false;
        }

        try {
            create();
        } catch (Exception e) {
            Status = "Can't create certificate.";
            return false;
        }

        ByteArrayOutputStream os = new ByteArrayOutputStream();
        PrintStream ps = new PrintStream(os);
        ps.println("Last CSR:");
        CSR.print(ps);
        ps.println();
        ps.println("Certificate:");
        Certificate.print(ps);
        ps.println();
        ps.println("IssuerAndSerialNumber:");
        IssuerAndSerialNumber.print(ps);
        ps.close();
        Status = os.toString();

        return true;
    
public byte[]getCertificate()
Returns DER encoded new certificate.

return
DER encoded new certificate

        return Certificate.getDERData();
    
public byte[]getIssuerAndSerialNumber()
Returns IssuerAndSerialNumber data structure for generated certificate.

return
IssuerAndSerialNumber data structure for generated certificate

        return IssuerAndSerialNumber.getDERData();
    
public byte[]getPkiPath()
Returns PkiPath data structure for generated certificate.

return
PkiPath data structure for generated certificate

        TLV PkiPath = new TLV(TLV.SEQUENCE_TYPE);
        try {
            PkiPath.child = new TLV(CACert.getEncoded(), 0);
        } catch (CertificateEncodingException e) {
            // it was already requested during initialization without
            // exception
        }
        PkiPath.child.next = Certificate;
        return PkiPath.getDERData();
    
private static synchronized longgetSerialNumber()
Returns the serial number value to be used for new certificate.

return
the serial number value.

        return SerialNumber++;
    
public java.lang.StringgetStatus()
Returns current status.

return
current status

        return Status;
    
public static synchronized booleaninit(java.lang.Object o)
Initializes the CA.

param
o servlet instance that should be used to obtain keystore or null if keystore should be opened as file.
return
true if initialization was successful.


                                               
          

        if (init) {
            return true;
        }

        try {
            InputStream keystoreStream;

            if (o == null) {
                keystoreStream =
                        new FileInputStream(new File(keystoreFilename));
            } else {
                keystoreStream =
                        o.getClass().getResourceAsStream(keystoreFilename);
            }
            KeyStore jcaKeystore =
                    KeyStore.getInstance(KeyStore.getDefaultType());

            try {

                if (keystorePassword == null) {
                    jcaKeystore.load(keystoreStream, null);
                } else {
                    jcaKeystore.load(keystoreStream,
                            keystorePassword.toCharArray());
                }
            } finally {
                keystoreStream.close();
            }

            // retrieve CA certificate and private key

            CACert = (java.security.cert.X509Certificate)
                    jcaKeystore.getCertificate(keyAlias);
            CAPrivKey = (PrivateKey) jcaKeystore.getKey(keyAlias,
                    keyPassword.toCharArray());

            String CASignOID = null;
            for (int i = 0 ; i < algorithms.length; i++) {
                if (CASign.equals(algorithms[i][2])) {
                    CASignOID = algorithms[i][0];
                    break;
                }
            }

            if (CASignOID == null) {
                return false;
            }

            // CA signature algorithm identifier
            CASignatureAlgorithm = new TLV(TLV.SEQUENCE_TYPE);
            CASignatureAlgorithm.child =
                    new TLV(TLV.OID_TYPE, TLV.StringToOID(CASignOID));
            CASignatureAlgorithm.child.next =
                    new TLV(TLV.NULL_TYPE, new byte[0]);

            // Parse CA certificate
            CACertPointer = new TLV(CACert.getEncoded(), 0);

            CACertPointer = CACertPointer.child.child;
            if (CACertPointer.type == TLV.VERSION_TYPE) {
                CACertPointer = CACertPointer.next;
            }
            // CACertPointer is at SerialNumber field

        } catch (Exception e){
            return false;
        }

        // serial number initial value

        Calendar c = Calendar.getInstance();
        long t = c.get(Calendar.YEAR) - 2000;
        t = t * 365 + c.get(Calendar.DAY_OF_YEAR) - 1;
        t = t * 24 + c.get(Calendar.HOUR_OF_DAY);
        t = t * 60 + c.get(Calendar.MINUTE);
        t = t * 60 + c.get(Calendar.SECOND);
        t = t * 1000 + c.get(Calendar.MILLISECOND);
        SerialNumber = t;

        init = true;

        return true;