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);
}
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");
}
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.");
}
}
Aggregations