FileDocCategorySizeDatePackage
JarUtils.javaAPI DocAndroid 1.5 API9201Wed May 06 22:41:06 BST 2009org.apache.harmony.security.utils

JarUtils

public class JarUtils extends Object
author
Boris Kuznetsov
version
$Revision$

Fields Summary
private static final int[]
MESSAGE_DIGEST_OID
Constructors Summary
Methods Summary
private static java.security.cert.X509Certificate[]createChain(java.security.cert.X509Certificate signer, java.security.cert.X509Certificate[] candidates)

        LinkedList chain = new LinkedList();
        chain.add(0, signer);

        // Signer is self-signed
        if (signer.getSubjectDN().equals(signer.getIssuerDN())){
            return (X509Certificate[])chain.toArray(new X509Certificate[1]);
        }

        Principal issuer = signer.getIssuerDN();
        X509Certificate issuerCert;
        int count = 1;
        while (true) {
            issuerCert = findCert(issuer, candidates);
            if( issuerCert == null) {
                break;
            }
            chain.add(issuerCert);
            count++;
            if (issuerCert.getSubjectDN().equals(issuerCert.getIssuerDN())) {
                break;
            }
            issuer = issuerCert.getIssuerDN();
        }
        return (X509Certificate[])chain.toArray(new X509Certificate[count]);
    
private static java.security.cert.X509CertificatefindCert(java.security.Principal issuer, java.security.cert.X509Certificate[] candidates)

        for (int i = 0; i < candidates.length; i++) {
            if (issuer.equals(candidates[i].getSubjectDN())) {
                return candidates[i];
            }
        }
        return null;
    
public static java.security.cert.Certificate[]verifySignature(java.io.InputStream signature, java.io.InputStream signatureBlock)
This method handle all the work with PKCS7, ASN1 encoding, signature verifying, and certification path building. See also PKCS #7: Cryptographic Message Syntax Standard: http://www.ietf.org/rfc/rfc2315.txt

param
signature - the input stream of signature file to be verified
param
signatureBlock - the input stream of corresponding signature block file
return
array of certificates used to verify the signature file
throws
IOException - if some errors occurs during reading from the stream
throws
GeneralSecurityException - if signature verification process fails


                                                                                          
          
                

        BerInputStream bis = new BerInputStream(signatureBlock);
        ContentInfo info = (ContentInfo)ContentInfo.ASN1.decode(bis);      
        SignedData signedData = info.getSignedData();
        if (signedData == null) {
            throw new IOException(Messages.getString("security.173")); //$NON-NLS-1$
        }
        Collection encCerts = signedData.getCertificates();
        if (encCerts.isEmpty()) {
            return null;
        }
        X509Certificate[] certs = new X509Certificate[encCerts.size()];
        int i = 0;
        for (Iterator it = encCerts.iterator(); it.hasNext();) {
            certs[i++]= new X509CertImpl((org.apache.harmony.security.x509.Certificate)it.next());
        }

        List sigInfos = signedData.getSignerInfos();
        SignerInfo sigInfo;
        if (!sigInfos.isEmpty()) {
            sigInfo = (SignerInfo)sigInfos.get(0);
        } else {
            return null;
        }

        // Issuer
        X500Principal issuer = sigInfo.getIssuer();

        // Certificate serial number
        BigInteger snum = sigInfo.getSerialNumber();

        // Locate the certificate
        int issuerSertIndex = 0;
        for (i = 0; i < certs.length; i++) {
            if (issuer.equals(certs[i].getIssuerDN()) && 
                    snum.equals(certs[i].getSerialNumber())) {
                issuerSertIndex = i;
                break;
            }
        }
        if (i == certs.length) { // No issuer certificate found
            return null;
        }

        if (certs[issuerSertIndex].hasUnsupportedCriticalExtension()) {
            throw new SecurityException(Messages.getString("security.174")); //$NON-NLS-1$
        }

        // Get Signature instance
        Signature sig = null;
        String da = sigInfo.getdigestAlgorithm();
        String dea = sigInfo.getDigestEncryptionAlgorithm();
        String alg = null;
        if (da != null && dea != null) {
            alg = da + "with" +  dea; //$NON-NLS-1$
            try{ 
                // BEGIN android-removed
                // sig = OpenSSLSignature.getInstance(alg);
                // END android-removed
                // BEGIN android-added
                sig = OpenSSLSignature.getInstance(alg);
                // END android-removed
            } catch (NoSuchAlgorithmException e) {}
        }
        if (sig == null) {
            alg = da;
            if (alg == null) {
                return null;
            }
            try{ 
                // BEGIN android-removed
                // sig = OpenSSLSignature.getInstance(alg);
                // END android-removed
                // BEGIN android-added
                sig = OpenSSLSignature.getInstance(alg);
                // END android-removed
            } catch (NoSuchAlgorithmException e) {
                return null;
            }
        }
        sig.initVerify(certs[issuerSertIndex]);

        // If the authenticatedAttributes field of SignerInfo contains more than zero attributes,
        // compute the message digest on the ASN.1 DER encoding of the Attributes value.
        // Otherwise, compute the message digest on the data.
        List atr = sigInfo.getAuthenticatedAttributes();

        byte[] sfBytes = new byte[signature.available()];
        signature.read(sfBytes);

        if (atr == null) {
            sig.update(sfBytes);    
        } else {
            sig.update(sigInfo.getEncodedAuthenticatedAttributes());

            // If the authenticatedAttributes field contains the message-digest attribute,
            // verify that it equals the computed digest of the signature file
            byte[] existingDigest = null;
            for (Iterator it = atr.iterator(); it.hasNext();) {
                AttributeTypeAndValue a = (AttributeTypeAndValue)it.next();
                if (Arrays.equals(a.getType().getOid(), MESSAGE_DIGEST_OID) ){
//TODO value                    existingDigest = a.AttributeValue;
                }
            }
            if (existingDigest != null) {
                // BEGIN android-removed
                // MessageDigest md = MessageDigest.getInstance(sigInfo.getDigestAlgorithm());
                // END android-removed
                // BEGIN android-added
                MessageDigest md = OpenSSLMessageDigestJDK.getInstance(sigInfo.getDigestAlgorithm());
                // END android-added
                byte[] computedDigest = md.digest(sfBytes);
                if (!Arrays.equals(existingDigest, computedDigest)) {
                    throw new SecurityException(Messages.getString("security.175")); //$NON-NLS-1$
                }
            }
        }

        if (!sig.verify(sigInfo.getEncryptedDigest())) {
            throw new SecurityException(Messages.getString("security.176")); //$NON-NLS-1$
        }

        return createChain(certs[issuerSertIndex], certs);