use of com.android.apksig.internal.x509.SubjectPublicKeyInfo in project pulsar by yahoo.
the class MessageCryptoBc method loadPublicKey.
private PublicKey loadPublicKey(byte[] keyBytes) throws Exception {
Reader keyReader = new StringReader(new String(keyBytes));
PublicKey publicKey = null;
try (PEMParser pemReader = new PEMParser(keyReader)) {
Object pemObj = pemReader.readObject();
JcaPEMKeyConverter pemConverter = new JcaPEMKeyConverter();
SubjectPublicKeyInfo keyInfo = null;
X9ECParameters ecParam = null;
if (pemObj instanceof ASN1ObjectIdentifier) {
// make sure this is EC Parameter we're handling. In which case
// we'll store it and read the next object which should be our
// EC Public Key
ASN1ObjectIdentifier ecOID = (ASN1ObjectIdentifier) pemObj;
ecParam = ECNamedCurveTable.getByOID(ecOID);
if (ecParam == null) {
throw new PEMException("Unable to find EC Parameter for the given curve oid: " + ((ASN1ObjectIdentifier) pemObj).getId());
}
pemObj = pemReader.readObject();
} else if (pemObj instanceof X9ECParameters) {
ecParam = (X9ECParameters) pemObj;
pemObj = pemReader.readObject();
}
if (pemObj instanceof X509CertificateHolder) {
keyInfo = ((X509CertificateHolder) pemObj).getSubjectPublicKeyInfo();
} else {
keyInfo = (SubjectPublicKeyInfo) pemObj;
}
publicKey = pemConverter.getPublicKey(keyInfo);
if (ecParam != null && ECDSA.equals(publicKey.getAlgorithm())) {
ECParameterSpec ecSpec = new ECParameterSpec(ecParam.getCurve(), ecParam.getG(), ecParam.getN(), ecParam.getH(), ecParam.getSeed());
KeyFactory keyFactory = KeyFactory.getInstance(ECDSA, BouncyCastleProvider.PROVIDER_NAME);
ECPublicKeySpec keySpec = new ECPublicKeySpec(((BCECPublicKey) publicKey).getQ(), ecSpec);
publicKey = keyFactory.generatePublic(keySpec);
}
} catch (IOException | NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException e) {
throw new Exception(e);
}
return publicKey;
}
use of com.android.apksig.internal.x509.SubjectPublicKeyInfo in project apksig by venshine.
the class ApkSigningBlockUtils method encodePublicKey.
public static byte[] encodePublicKey(PublicKey publicKey) throws InvalidKeyException, NoSuchAlgorithmException {
byte[] encodedPublicKey = null;
if ("X.509".equals(publicKey.getFormat())) {
encodedPublicKey = publicKey.getEncoded();
// if the key is an RSA key check for a negative modulus
String keyAlgorithm = publicKey.getAlgorithm();
if ("RSA".equals(keyAlgorithm) || OID_RSA_ENCRYPTION.equals(keyAlgorithm)) {
try {
// Parse the encoded public key into the separate elements of the
// SubjectPublicKeyInfo to obtain the SubjectPublicKey.
ByteBuffer encodedPublicKeyBuffer = ByteBuffer.wrap(encodedPublicKey);
SubjectPublicKeyInfo subjectPublicKeyInfo = Asn1BerParser.parse(encodedPublicKeyBuffer, SubjectPublicKeyInfo.class);
// The SubjectPublicKey is encoded as a bit string within the
// SubjectPublicKeyInfo. The first byte of the encoding is the number of padding
// bits; store this and decode the rest of the bit string into the RSA modulus
// and exponent.
ByteBuffer subjectPublicKeyBuffer = subjectPublicKeyInfo.subjectPublicKey;
byte padding = subjectPublicKeyBuffer.get();
RSAPublicKey rsaPublicKey = Asn1BerParser.parse(subjectPublicKeyBuffer, RSAPublicKey.class);
// byte.
if (rsaPublicKey.modulus.compareTo(BigInteger.ZERO) < 0) {
// A negative modulus indicates the leading bit in the integer is 1. Per
// ASN.1 encoding rules to encode a positive integer with the leading bit
// set to 1 a byte containing all zeros should precede the integer encoding.
byte[] encodedModulus = rsaPublicKey.modulus.toByteArray();
byte[] reencodedModulus = new byte[encodedModulus.length + 1];
reencodedModulus[0] = 0;
System.arraycopy(encodedModulus, 0, reencodedModulus, 1, encodedModulus.length);
rsaPublicKey.modulus = new BigInteger(reencodedModulus);
// Once the modulus has been corrected reencode the RSAPublicKey, then
// restore the padding value in the bit string and reencode the entire
// SubjectPublicKeyInfo to be returned to the caller.
byte[] reencodedRSAPublicKey = Asn1DerEncoder.encode(rsaPublicKey);
byte[] reencodedSubjectPublicKey = new byte[reencodedRSAPublicKey.length + 1];
reencodedSubjectPublicKey[0] = padding;
System.arraycopy(reencodedRSAPublicKey, 0, reencodedSubjectPublicKey, 1, reencodedRSAPublicKey.length);
subjectPublicKeyInfo.subjectPublicKey = ByteBuffer.wrap(reencodedSubjectPublicKey);
encodedPublicKey = Asn1DerEncoder.encode(subjectPublicKeyInfo);
}
} catch (Asn1DecodingException | Asn1EncodingException e) {
System.out.println("Caught a exception encoding the public key: " + e);
e.printStackTrace();
encodedPublicKey = null;
}
}
}
if (encodedPublicKey == null) {
try {
encodedPublicKey = KeyFactory.getInstance(publicKey.getAlgorithm()).getKeySpec(publicKey, X509EncodedKeySpec.class).getEncoded();
} catch (InvalidKeySpecException e) {
throw new InvalidKeyException("Failed to obtain X.509 encoded form of public key " + publicKey + " of class " + publicKey.getClass().getName(), e);
}
}
if ((encodedPublicKey == null) || (encodedPublicKey.length == 0)) {
throw new InvalidKeyException("Failed to obtain X.509 encoded form of public key " + publicKey + " of class " + publicKey.getClass().getName());
}
return encodedPublicKey;
}
use of com.android.apksig.internal.x509.SubjectPublicKeyInfo in project apksig by venshine.
the class ApkSignerTest method getRSAPublicKeyFromSigningBlock.
private RSAPublicKey getRSAPublicKeyFromSigningBlock(File apk, int signatureVersionId) throws Exception {
int signatureVersionBlockId;
switch(signatureVersionId) {
case ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V2:
signatureVersionBlockId = V2SchemeConstants.APK_SIGNATURE_SCHEME_V2_BLOCK_ID;
break;
case ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V3:
signatureVersionBlockId = V3SchemeConstants.APK_SIGNATURE_SCHEME_V3_BLOCK_ID;
break;
default:
throw new Exception("Invalid signature version ID specified: " + signatureVersionId);
}
SignatureInfo signatureInfo = getSignatureInfoFromApk(apk, signatureVersionId, signatureVersionBlockId);
// FORMAT:
// * length prefixed sequence of length prefixed signers
// * length-prefixed signed data
// * V3+ only - minSDK (uint32)
// * V3+ only - maxSDK (uint32)
// * length-prefixed sequence of length-prefixed signatures:
// * length-prefixed bytes: public key (X.509 SubjectPublicKeyInfo, ASN.1 DER encoded)
ByteBuffer signers = ApkSigningBlockUtils.getLengthPrefixedSlice(signatureInfo.signatureBlock);
ByteBuffer signer = ApkSigningBlockUtils.getLengthPrefixedSlice(signers);
// Since all the data is read from the signer block the signedData and signatures are
// discarded.
ApkSigningBlockUtils.getLengthPrefixedSlice(signer);
// For V3+ signature version IDs discard the min / max SDKs as well
if (signatureVersionId >= ApkSigningBlockUtils.VERSION_APK_SIGNATURE_SCHEME_V3) {
signer.getInt();
signer.getInt();
}
ApkSigningBlockUtils.getLengthPrefixedSlice(signer);
ByteBuffer publicKey = ApkSigningBlockUtils.getLengthPrefixedSlice(signer);
SubjectPublicKeyInfo subjectPublicKeyInfo = Asn1BerParser.parse(publicKey, SubjectPublicKeyInfo.class);
ByteBuffer subjectPublicKeyBuffer = subjectPublicKeyInfo.subjectPublicKey;
// The SubjectPublicKey is stored as a bit string in the SubjectPublicKeyInfo with the first
// byte indicating the number of padding bits in the public key. Read this first byte to
// allow parsing the rest of the RSAPublicKey as a sequence.
subjectPublicKeyBuffer.get();
return Asn1BerParser.parse(subjectPublicKeyBuffer, RSAPublicKey.class);
}
use of com.android.apksig.internal.x509.SubjectPublicKeyInfo in project kafka by apache.
the class TestSslUtils method generateCertificate.
/**
* Create a self-signed X.509 Certificate.
* From http://bfo.com/blog/2011/03/08/odds_and_ends_creating_a_new_x_509_certificate.html.
*
* @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
* @param pair the KeyPair
* @param days how many days from now the Certificate is valid for
* @param algorithm the signing algorithm, eg "SHA1withRSA"
* @return the self-signed certificate
* @throws CertificateException thrown if a security error or an IO error occurred.
*/
public static X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm) throws CertificateException {
try {
Security.addProvider(new BouncyCastleProvider());
AlgorithmIdentifier sigAlgId = new DefaultSignatureAlgorithmIdentifierFinder().find(algorithm);
AlgorithmIdentifier digAlgId = new DefaultDigestAlgorithmIdentifierFinder().find(sigAlgId);
AsymmetricKeyParameter privateKeyAsymKeyParam = PrivateKeyFactory.createKey(pair.getPrivate().getEncoded());
SubjectPublicKeyInfo subPubKeyInfo = SubjectPublicKeyInfo.getInstance(pair.getPublic().getEncoded());
ContentSigner sigGen = new BcRSAContentSignerBuilder(sigAlgId, digAlgId).build(privateKeyAsymKeyParam);
X500Name name = new X500Name(dn);
Date from = new Date();
Date to = new Date(from.getTime() + days * 86400000L);
BigInteger sn = new BigInteger(64, new SecureRandom());
X509v1CertificateBuilder v1CertGen = new X509v1CertificateBuilder(name, sn, from, to, name, subPubKeyInfo);
X509CertificateHolder certificateHolder = v1CertGen.build(sigGen);
return new JcaX509CertificateConverter().setProvider("BC").getCertificate(certificateHolder);
} catch (CertificateException ce) {
throw ce;
} catch (Exception e) {
throw new CertificateException(e);
}
}
use of com.android.apksig.internal.x509.SubjectPublicKeyInfo in project XobotOS by xamarin.
the class X509CertSelector method match.
/**
* Returns whether the specified certificate matches all the criteria
* collected in this instance.
*
* @param certificate
* the certificate to check.
* @return {@code true} if the certificate matches all the criteria,
* otherwise {@code false}.
*/
public boolean match(Certificate certificate) {
if (!(certificate instanceof X509Certificate)) {
return false;
}
X509Certificate cert = (X509Certificate) certificate;
if ((certificateEquals != null) && !certificateEquals.equals(cert)) {
return false;
}
if ((serialNumber != null) && !serialNumber.equals(cert.getSerialNumber())) {
return false;
}
if ((issuer != null) && !issuer.equals(cert.getIssuerX500Principal())) {
return false;
}
if ((subject != null) && !subject.equals(cert.getSubjectX500Principal())) {
return false;
}
if ((subjectKeyIdentifier != null) && !Arrays.equals(subjectKeyIdentifier, // are taken from rfc 3280 (http://www.ietf.org/rfc/rfc3280.txt)
getExtensionValue(cert, "2.5.29.14"))) {
return false;
}
if ((authorityKeyIdentifier != null) && !Arrays.equals(authorityKeyIdentifier, getExtensionValue(cert, "2.5.29.35"))) {
return false;
}
if (certificateValid != null) {
try {
cert.checkValidity(certificateValid);
} catch (CertificateExpiredException e) {
return false;
} catch (CertificateNotYetValidException e) {
return false;
}
}
if (privateKeyValid != null) {
try {
byte[] bytes = getExtensionValue(cert, "2.5.29.16");
if (bytes == null) {
return false;
}
PrivateKeyUsagePeriod pkup = (PrivateKeyUsagePeriod) PrivateKeyUsagePeriod.ASN1.decode(bytes);
Date notBefore = pkup.getNotBefore();
Date notAfter = pkup.getNotAfter();
if ((notBefore == null) && (notAfter == null)) {
return false;
}
if ((notBefore != null) && notBefore.compareTo(privateKeyValid) > 0) {
return false;
}
if ((notAfter != null) && notAfter.compareTo(privateKeyValid) < 0) {
return false;
}
} catch (IOException e) {
return false;
}
}
if (subjectPublicKeyAlgID != null) {
try {
byte[] encoding = cert.getPublicKey().getEncoded();
AlgorithmIdentifier ai = ((SubjectPublicKeyInfo) SubjectPublicKeyInfo.ASN1.decode(encoding)).getAlgorithmIdentifier();
if (!subjectPublicKeyAlgID.equals(ai.getAlgorithm())) {
return false;
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
if (subjectPublicKey != null) {
if (!Arrays.equals(subjectPublicKey, cert.getPublicKey().getEncoded())) {
return false;
}
}
if (keyUsage != null) {
boolean[] ku = cert.getKeyUsage();
if (ku != null) {
int i = 0;
int min_length = (ku.length < keyUsage.length) ? ku.length : keyUsage.length;
for (; i < min_length; i++) {
if (keyUsage[i] && !ku[i]) {
// but certificate does not.
return false;
}
}
for (; i < keyUsage.length; i++) {
if (keyUsage[i]) {
return false;
}
}
}
}
if (extendedKeyUsage != null) {
try {
List keyUsage = cert.getExtendedKeyUsage();
if (keyUsage != null) {
if (!keyUsage.containsAll(extendedKeyUsage)) {
return false;
}
}
} catch (CertificateParsingException e) {
return false;
}
}
if (pathLen != -1) {
int p_len = cert.getBasicConstraints();
if ((pathLen < 0) && (p_len >= 0)) {
// need end-entity but got CA
return false;
}
if ((pathLen > 0) && (pathLen > p_len)) {
// allowed _pathLen is small
return false;
}
}
if (subjectAltNames != null) {
PASSED: try {
byte[] bytes = getExtensionValue(cert, "2.5.29.17");
if (bytes == null) {
return false;
}
List<GeneralName> sans = ((GeneralNames) GeneralNames.ASN1.decode(bytes)).getNames();
if ((sans == null) || (sans.size() == 0)) {
return false;
}
boolean[][] map = new boolean[9][];
// initialize the check map
for (int i = 0; i < 9; i++) {
map[i] = (subjectAltNames[i] == null) ? EmptyArray.BOOLEAN : new boolean[subjectAltNames[i].size()];
}
for (GeneralName name : sans) {
int tag = name.getTag();
for (int i = 0; i < map[tag].length; i++) {
if (subjectAltNames[tag].get(i).equals(name)) {
if (!matchAllNames) {
break PASSED;
}
map[tag][i] = true;
}
}
}
if (!matchAllNames) {
// there was not any match
return false;
}
// else check the map
for (int tag = 0; tag < 9; tag++) {
for (int name = 0; name < map[tag].length; name++) {
if (!map[tag][name]) {
return false;
}
}
}
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
if (nameConstraints != null) {
if (!nameConstraints.isAcceptable(cert)) {
return false;
}
}
if (policies != null) {
byte[] bytes = getExtensionValue(cert, "2.5.29.32");
if (bytes == null) {
return false;
}
if (policies.size() == 0) {
// one policy in it.
return true;
}
PASSED: try {
List<PolicyInformation> policyInformations = ((CertificatePolicies) CertificatePolicies.ASN1.decode(bytes)).getPolicyInformations();
for (PolicyInformation policyInformation : policyInformations) {
if (policies.contains(policyInformation.getPolicyIdentifier())) {
break PASSED;
}
}
return false;
} catch (IOException e) {
// the extension is invalid
return false;
}
}
if (pathToNames != null) {
byte[] bytes = getExtensionValue(cert, "2.5.29.30");
if (bytes != null) {
NameConstraints nameConstraints;
try {
nameConstraints = (NameConstraints) NameConstraints.ASN1.decode(bytes);
} catch (IOException e) {
// the extension is invalid;
return false;
}
if (!nameConstraints.isAcceptable(pathToNames)) {
return false;
}
}
}
return true;
}
Aggregations