Search in sources :

Example 1 with SigningCertificateNode

use of com.android.apksig.internal.apk.v3.V3SigningCertificateLineage.SigningCertificateNode in project apksig by venshine.

the class SigningCertificateLineage method spawnDescendant.

/**
 * Add a new signing certificate to the lineage.  This effectively creates a signing certificate
 * rotation event, forcing APKs which include this lineage to be signed by the new signer.
 *
 * @param parent current signing certificate of the containing APK
 * @param child new signing certificate which will sign the APK contents
 * @param childCapabilities flags
 */
public SigningCertificateLineage spawnDescendant(SignerConfig parent, SignerConfig child, SignerCapabilities childCapabilities) throws CertificateEncodingException, InvalidKeyException, NoSuchAlgorithmException, SignatureException {
    if (parent == null) {
        throw new NullPointerException("parent == null");
    }
    if (child == null) {
        throw new NullPointerException("child == null");
    }
    if (childCapabilities == null) {
        throw new NullPointerException("childCapabilities == null");
    }
    if (mSigningLineage.isEmpty()) {
        throw new IllegalArgumentException("Cannot spawn descendant signing certificate on an" + " empty SigningCertificateLineage: no parent node");
    }
    // make sure that the parent matches our newest generation (leaf node/sink)
    SigningCertificateNode currentGeneration = mSigningLineage.get(mSigningLineage.size() - 1);
    if (!Arrays.equals(currentGeneration.signingCert.getEncoded(), parent.getCertificate().getEncoded())) {
        throw new IllegalArgumentException("SignerConfig Certificate containing private key" + " to sign the new SigningCertificateLineage record does not match the" + " existing most recent record");
    }
    // create data to be signed, including the algorithm we're going to use
    SignatureAlgorithm signatureAlgorithm = getSignatureAlgorithm(parent);
    ByteBuffer prefixedSignedData = ByteBuffer.wrap(V3SigningCertificateLineage.encodeSignedData(child.getCertificate(), signatureAlgorithm.getId()));
    prefixedSignedData.position(4);
    ByteBuffer signedDataBuffer = ByteBuffer.allocate(prefixedSignedData.remaining());
    signedDataBuffer.put(prefixedSignedData);
    byte[] signedData = signedDataBuffer.array();
    // create SignerConfig to do the signing
    List<X509Certificate> certificates = new ArrayList<>(1);
    certificates.add(parent.getCertificate());
    ApkSigningBlockUtils.SignerConfig newSignerConfig = new ApkSigningBlockUtils.SignerConfig();
    newSignerConfig.privateKey = parent.getPrivateKey();
    newSignerConfig.certificates = certificates;
    newSignerConfig.signatureAlgorithms = Collections.singletonList(signatureAlgorithm);
    // sign it
    List<Pair<Integer, byte[]>> signatures = ApkSigningBlockUtils.generateSignaturesOverData(newSignerConfig, signedData);
    // finally, add it to our lineage
    SignatureAlgorithm sigAlgorithm = SignatureAlgorithm.findById(signatures.get(0).getFirst());
    byte[] signature = signatures.get(0).getSecond();
    currentGeneration.sigAlgorithm = sigAlgorithm;
    SigningCertificateNode childNode = new SigningCertificateNode(child.getCertificate(), sigAlgorithm, null, signature, childCapabilities.getFlags());
    List<SigningCertificateNode> lineageCopy = new ArrayList<>(mSigningLineage);
    lineageCopy.add(childNode);
    return new SigningCertificateLineage(mMinSdkVersion, lineageCopy);
}
Also used : ArrayList(java.util.ArrayList) SignatureAlgorithm(com.android.apksig.internal.apk.SignatureAlgorithm) ApkSigningBlockUtils(com.android.apksig.internal.apk.ApkSigningBlockUtils) ByteBuffer(java.nio.ByteBuffer) X509Certificate(java.security.cert.X509Certificate) V3SigningCertificateLineage(com.android.apksig.internal.apk.v3.V3SigningCertificateLineage) SigningCertificateNode(com.android.apksig.internal.apk.v3.V3SigningCertificateLineage.SigningCertificateNode) Pair(com.android.apksig.internal.util.Pair)

Example 2 with SigningCertificateNode

use of com.android.apksig.internal.apk.v3.V3SigningCertificateLineage.SigningCertificateNode in project apksig by venshine.

the class SigningCertificateLineage method updateSignerCapabilities.

/**
 * Updates the SignerCapabilities for the signer in the lineage that matches the provided
 * config. Only those capabilities that have been modified through the setXX methods will be
 * updated for the signer to prevent unset default values from being applied.
 */
public void updateSignerCapabilities(SignerConfig config, SignerCapabilities capabilities) {
    if (config == null) {
        throw new NullPointerException("config == null");
    }
    X509Certificate cert = config.getCertificate();
    for (int i = 0; i < mSigningLineage.size(); i++) {
        SigningCertificateNode lineageNode = mSigningLineage.get(i);
        if (lineageNode.signingCert.equals(cert)) {
            int flags = lineageNode.flags;
            SignerCapabilities newCapabilities = new SignerCapabilities.Builder(flags).setCallerConfiguredCapabilities(capabilities).build();
            lineageNode.flags = newCapabilities.getFlags();
            return;
        }
    }
    // the provided signer config was not found in the lineage
    throw new IllegalArgumentException("Certificate (" + cert.getSubjectDN() + ") not found in the SigningCertificateLineage");
}
Also used : SigningCertificateNode(com.android.apksig.internal.apk.v3.V3SigningCertificateLineage.SigningCertificateNode) X509Certificate(java.security.cert.X509Certificate)

Example 3 with SigningCertificateNode

use of com.android.apksig.internal.apk.v3.V3SigningCertificateLineage.SigningCertificateNode in project apksig by venshine.

the class SigningCertificateLineage method read.

private static SigningCertificateLineage read(ByteBuffer inputByteBuffer, int version) throws IOException {
    switch(version) {
        case FIRST_VERSION:
            try {
                List<SigningCertificateNode> nodes = V3SigningCertificateLineage.readSigningCertificateLineage(getLengthPrefixedSlice(inputByteBuffer));
                int minSdkVersion = calculateMinSdkVersion(nodes);
                return new SigningCertificateLineage(minSdkVersion, nodes);
            } catch (ApkFormatException e) {
                // unable to get a proper length-prefixed lineage slice
                throw new IOException("Unable to read list of signing certificate nodes in " + "SigningCertificateLineage", e);
            }
        default:
            throw new IllegalArgumentException("Improper SigningCertificateLineage format: unrecognized version.");
    }
}
Also used : V3SigningCertificateLineage(com.android.apksig.internal.apk.v3.V3SigningCertificateLineage) ApkFormatException(com.android.apksig.apk.ApkFormatException) SigningCertificateNode(com.android.apksig.internal.apk.v3.V3SigningCertificateLineage.SigningCertificateNode) IOException(java.io.IOException)

Aggregations

SigningCertificateNode (com.android.apksig.internal.apk.v3.V3SigningCertificateLineage.SigningCertificateNode)3 V3SigningCertificateLineage (com.android.apksig.internal.apk.v3.V3SigningCertificateLineage)2 X509Certificate (java.security.cert.X509Certificate)2 ApkFormatException (com.android.apksig.apk.ApkFormatException)1 ApkSigningBlockUtils (com.android.apksig.internal.apk.ApkSigningBlockUtils)1 SignatureAlgorithm (com.android.apksig.internal.apk.SignatureAlgorithm)1 Pair (com.android.apksig.internal.util.Pair)1 IOException (java.io.IOException)1 ByteBuffer (java.nio.ByteBuffer)1 ArrayList (java.util.ArrayList)1