use of com.android.apksig.internal.pkcs7.SignerInfo in project XobotOS by xamarin.
the class JarUtils method verifySignature.
/**
* 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
*/
public static Certificate[] verifySignature(InputStream signature, InputStream signatureBlock) throws IOException, GeneralSecurityException {
BerInputStream bis = new BerInputStream(signatureBlock);
ContentInfo info = (ContentInfo) ContentInfo.ASN1.decode(bis);
SignedData signedData = info.getSignedData();
if (signedData == null) {
throw new IOException("No SignedData found");
}
Collection<org.apache.harmony.security.x509.Certificate> encCerts = signedData.getCertificates();
if (encCerts.isEmpty()) {
return null;
}
X509Certificate[] certs = new X509Certificate[encCerts.size()];
int i = 0;
for (org.apache.harmony.security.x509.Certificate encCert : encCerts) {
certs[i++] = new X509CertImpl(encCert);
}
List<SignerInfo> sigInfos = signedData.getSignerInfos();
SignerInfo sigInfo;
if (!sigInfos.isEmpty()) {
sigInfo = 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("Can not recognize a critical extension");
}
// 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;
try {
sig = OpenSSLSignature.getInstance(alg);
} catch (NoSuchAlgorithmException e) {
}
}
if (sig == null) {
alg = da;
if (alg == null) {
return null;
}
try {
sig = OpenSSLSignature.getInstance(alg);
} 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<AttributeTypeAndValue> 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 (AttributeTypeAndValue a : atr) {
if (Arrays.equals(a.getType().getOid(), MESSAGE_DIGEST_OID)) {
//TODO value existingDigest = a.AttributeValue;
}
}
if (existingDigest != null) {
MessageDigest md = MessageDigest.getInstance(sigInfo.getDigestAlgorithm());
byte[] computedDigest = md.digest(sfBytes);
if (!Arrays.equals(existingDigest, computedDigest)) {
throw new SecurityException("Incorrect MD");
}
}
}
if (!sig.verify(sigInfo.getEncryptedDigest())) {
throw new SecurityException("Incorrect signature");
}
return createChain(certs[issuerSertIndex], certs);
}
use of com.android.apksig.internal.pkcs7.SignerInfo in project apksig by venshine.
the class ApkSigningBlockUtils method generatePkcs7DerEncodedMessage.
/**
* Wrap the signature according to CMS PKCS #7 RFC 5652.
* The high-level simplified structure is as follows:
* // ContentInfo
* // digestAlgorithm
* // SignedData
* // bag of certificates
* // SignerInfo
* // signing cert issuer and serial number (for locating the cert in the above bag)
* // digestAlgorithm
* // signatureAlgorithm
* // signature
*
* @throws Asn1EncodingException if the ASN.1 structure could not be encoded
*/
public static byte[] generatePkcs7DerEncodedMessage(byte[] signatureBytes, ByteBuffer data, List<X509Certificate> signerCerts, AlgorithmIdentifier digestAlgorithmId, AlgorithmIdentifier signatureAlgorithmId) throws Asn1EncodingException, CertificateEncodingException {
SignerInfo signerInfo = new SignerInfo();
signerInfo.version = 1;
X509Certificate signingCert = signerCerts.get(0);
X500Principal signerCertIssuer = signingCert.getIssuerX500Principal();
signerInfo.sid = new SignerIdentifier(new IssuerAndSerialNumber(new Asn1OpaqueObject(signerCertIssuer.getEncoded()), signingCert.getSerialNumber()));
signerInfo.digestAlgorithm = digestAlgorithmId;
signerInfo.signatureAlgorithm = signatureAlgorithmId;
signerInfo.signature = ByteBuffer.wrap(signatureBytes);
SignedData signedData = new SignedData();
signedData.certificates = new ArrayList<>(signerCerts.size());
for (X509Certificate cert : signerCerts) {
signedData.certificates.add(new Asn1OpaqueObject(cert.getEncoded()));
}
signedData.version = 1;
signedData.digestAlgorithms = Collections.singletonList(digestAlgorithmId);
signedData.encapContentInfo = new EncapsulatedContentInfo(Pkcs7Constants.OID_DATA);
// If data is not null, data will be embedded as is in the result -- an attached pcsk7
signedData.encapContentInfo.content = data;
signedData.signerInfos = Collections.singletonList(signerInfo);
ContentInfo contentInfo = new ContentInfo();
contentInfo.contentType = Pkcs7Constants.OID_SIGNED_DATA;
contentInfo.content = new Asn1OpaqueObject(Asn1DerEncoder.encode(signedData));
return Asn1DerEncoder.encode(contentInfo);
}
Aggregations