/** Write the certificate file with a digital signature. */ private void writeSignatureBlock(Signature signature, X509Certificate publicKey, PrivateKey privateKey) throws IOException, GeneralSecurityException { SignerInfo signerInfo = new SignerInfo( new X500Name(publicKey.getIssuerX500Principal().getName()), publicKey.getSerialNumber(), AlgorithmId.get(DIGEST_ALGORITHM), AlgorithmId.get(privateKey.getAlgorithm()), signature.sign()); PKCS7 pkcs7 = new PKCS7( new AlgorithmId[] { AlgorithmId.get(DIGEST_ALGORITHM) }, new ContentInfo(ContentInfo.DATA_OID, null), new X509Certificate[] { publicKey }, new SignerInfo[] { signerInfo }); pkcs7.encodeSignedData(mOutputJar); }
/** * Decode the signature data. Verify that the object identifier matches * and return the message digest. */ public static byte[] decodeSignature(ObjectIdentifier oid, byte[] signature) throws IOException { DerInputStream in = new DerInputStream(signature); DerValue[] values = in.getSequence(2); if ((values.length != 2) || (in.available() != 0)) { throw new IOException("SEQUENCE length error"); } AlgorithmId algId = AlgorithmId.parse(values[0]); if (algId.getOID().equals((Object)oid) == false) { throw new IOException("ObjectIdentifier mismatch: " + algId.getOID()); } if (algId.getEncodedParams() != null) { throw new IOException("Unexpected AlgorithmId parameters"); } byte[] digest = values[1].getOctetString(); return digest; }
/** * Construct a key from its components. Used by the * KeyFactory. */ ECPrivateKeyImpl(BigInteger s, ECParameterSpec params) throws InvalidKeyException { this.s = s; this.params = params; // generate the encoding algid = new AlgorithmId (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params)); try { DerOutputStream out = new DerOutputStream(); out.putInteger(1); // version 1 byte[] privBytes = ECUtil.trimZeroes(s.toByteArray()); out.putOctetString(privBytes); DerValue val = new DerValue(DerValue.tag_Sequence, out.toByteArray()); key = val.toByteArray(); } catch (IOException exc) { // should never occur throw new InvalidKeyException(exc); } }
public SignerInfo(X500Name issuerName, BigInteger serial, AlgorithmId digestAlgorithmId, PKCS9Attributes authenticatedAttributes, AlgorithmId digestEncryptionAlgorithmId, byte[] encryptedDigest, PKCS9Attributes unauthenticatedAttributes) { this.version = BigInteger.ONE; this.issuerName = issuerName; this.certificateSerialNumber = serial; this.digestAlgorithmId = digestAlgorithmId; this.authenticatedAttributes = authenticatedAttributes; this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId; this.encryptedDigest = encryptedDigest; this.unauthenticatedAttributes = unauthenticatedAttributes; }
/** * Constructs an <code>EncryptedPrivateKeyInfo</code> from the * encryption algorithm parameters and the encrypted data. * * @param algParams the algorithm parameters for the encryption * algorithm. <code>algParams.getEncoded()</code> should return * the ASN.1 encoded bytes of the <code>parameters</code> field * of the <code>AlgorithmIdentifer</code> component of the * <code>EncryptedPrivateKeyInfo</code> type. * @param encryptedData encrypted data. The contents of * <code>encrypedData</code> are copied to protect against * subsequent modification when constructing this object. * @exception NullPointerException if <code>algParams</code> or * <code>encryptedData</code> is null. * @exception IllegalArgumentException if <code>encryptedData</code> * is empty, i.e. 0-length. * @exception NoSuchAlgorithmException if the specified algName of * the specified <code>algParams</code> parameter is not supported. */ public EncryptedPrivateKeyInfo(AlgorithmParameters algParams, byte[] encryptedData) throws NoSuchAlgorithmException { if (algParams == null) { throw new NullPointerException("algParams must be non-null"); } this.algid = AlgorithmId.get(algParams); if (encryptedData == null) { throw new NullPointerException("encryptedData must be non-null"); } else if (encryptedData.length == 0) { throw new IllegalArgumentException("the encryptedData " + "parameter must not be empty"); } else { this.encryptedData = encryptedData.clone(); } // delay the generation of ASN.1 encoding until // getEncoded() is called this.encoded = null; }
/** * Create the signed certificate request. This will later be * retrieved in either string or binary format. * * @param subject identifies the signer (by X.500 name). * @param signature private key and signing algorithm to use. * @exception IOException on errors. * @exception CertificateException on certificate handling errors. * @exception SignatureException on signature handling errors. */ public void encodeAndSign(X500Name subject, Signature signature) throws CertificateException, IOException, SignatureException { DerOutputStream out, scratch; byte[] certificateRequestInfo; byte[] sig; if (encoded != null) throw new SignatureException("request is already signed"); this.subject = subject; /* * Encode cert request info, wrap in a sequence for signing */ scratch = new DerOutputStream(); scratch.putInteger(BigInteger.ZERO); // PKCS #10 v1.0 subject.encode(scratch); // X.500 name scratch.write(subjectPublicKeyInfo.getEncoded()); // public key attributeSet.encode(scratch); out = new DerOutputStream(); out.write(DerValue.tag_Sequence, scratch); // wrap it! certificateRequestInfo = out.toByteArray(); scratch = out; /* * Sign it ... */ signature.update(certificateRequestInfo, 0, certificateRequestInfo.length); sig = signature.sign(); /* * Build guts of SIGNED macro */ AlgorithmId algId = null; try { algId = AlgorithmId.get(signature.getAlgorithm()); } catch (NoSuchAlgorithmException nsae) { throw new SignatureException(nsae); } algId.encode(scratch); // sig algorithm scratch.putBitString(sig); // sig /* * Wrap those guts in a sequence */ out = new DerOutputStream(); out.write(DerValue.tag_Sequence, scratch); encoded = out.toByteArray(); }
/** * Constructs (i.e., parses) an <code>EncryptedPrivateKeyInfo</code> from * its encoding. */ EncryptedPrivateKeyInfo(byte[] encoded) throws IOException { DerValue val = new DerValue(encoded); DerValue[] seq = new DerValue[2]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); if (val.data.available() != 0) { throw new IOException("overrun, bytes = " + val.data.available()); } this.algid = AlgorithmId.parse(seq[0]); if (seq[0].data.available() != 0) { throw new IOException("encryptionAlgorithm field overrun"); } this.encryptedData = seq[1].getOctetString(); if (seq[1].data.available() != 0) throw new IOException("encryptedData field overrun"); this.encoded = encoded.clone(); }
/** * Constructs a PKCS#8 PrivateKeyInfo from its ASN.1 encoding. */ PrivateKeyInfo(byte[] encoded) throws IOException { DerValue val = new DerValue(encoded); if (val.tag != DerValue.tag_Sequence) throw new IOException("private key parse error: not a sequence"); // version BigInteger parsedVersion = val.data.getBigInteger(); if (!parsedVersion.equals(VERSION)) { throw new IOException("version mismatch: (supported: " + VERSION + ", parsed: " + parsedVersion); } // privateKeyAlgorithm this.algid = AlgorithmId.parse(val.data.getDerValue()); // privateKey this.privkey = val.data.getOctetString(); // OPTIONAL attributes not supported yet }
/** * Construct a key from its components. Used by the * KeyFactory. */ public ECPrivateKeyImpl(BigInteger s, ECParameterSpec params) throws InvalidKeyException { this.s = s; this.params = params; // generate the encoding algid = new AlgorithmId (AlgorithmId.EC_oid, ECParameters.getAlgorithmParameters(params)); try { DerOutputStream out = new DerOutputStream(); out.putInteger(1); // version 1 byte[] privBytes = ECUtil.trimZeroes(s.toByteArray()); out.putOctetString(privBytes); DerValue val = new DerValue(DerValue.tag_Sequence, out.toByteArray()); key = val.toByteArray(); } catch (IOException exc) { // should never occur throw new InvalidKeyException(exc); } }
/** * Decode the signature data. Verify that the object identifier matches * and return the message digest. */ public static byte[] decodeSignature(ObjectIdentifier oid, byte[] sig) throws IOException { // Enforce strict DER checking for signatures DerInputStream in = new DerInputStream(sig, 0, sig.length, false); DerValue[] values = in.getSequence(2); if ((values.length != 2) || (in.available() != 0)) { throw new IOException("SEQUENCE length error"); } AlgorithmId algId = AlgorithmId.parse(values[0]); if (algId.getOID().equals(oid) == false) { throw new IOException("ObjectIdentifier mismatch: " + algId.getOID()); } if (algId.getEncodedParams() != null) { throw new IOException("Unexpected AlgorithmId parameters"); } byte[] digest = values[1].getOctetString(); return digest; }
public static void main(String[] args) throws Throwable { final String[] algorithmNames = { "PBKDF2WITHHMACSHA1", "PBEWITHMD5ANDDES", "DSA", "SHA384WITHRSA", "RSA", "SHA1WITHDSA", "SHA512WITHRSA", "MD2WITHRSA", "PBEWITHSHA1ANDDESEDE", "SHA1WITHRSA", "DIFFIEHELLMAN", "MD5WITHRSA", "PBEWITHSHA1ANDRC2_40", "SHA256WITHRSA", }; final int THREADS = 2; final ExecutorService pool = Executors.newFixedThreadPool(THREADS); final CountDownLatch startingGate = new CountDownLatch(THREADS); final Runnable r = new Runnable() { public void run() { startingGate.countDown(); do {} while (startingGate.getCount() > 0); try { for (String algorithmName : algorithmNames) AlgorithmId.get(algorithmName); } catch (Throwable fail) { throw new AssertionError(fail); } }}; final ArrayList<Future<?>> futures = new ArrayList<>(); for (int i = 0; i < THREADS; i++) futures.add(pool.submit(r)); pool.shutdown(); for (Future<?> future : futures) future.get(); }
private ObjectIdentifier getCertPubKeyAlgOID(X509Certificate xcert) throws IOException { byte[] encodedKey = xcert.getPublicKey().getEncoded(); DerValue val = new DerValue(encodedKey); if (val.tag != DerValue.tag_Sequence) { throw new RuntimeException("invalid key format"); } return AlgorithmId.parse(val.data.getDerValue()).getOID(); }
/** * Check the signature algorithm with the specified public key. * * @param key the public key to verify the CRL signature * @param algorithmId signature algorithm Algorithm ID * @param variant is the Validator variants of the operation. A null value * passed will set it to Validator.GENERIC. */ static void check(PublicKey key, AlgorithmId algorithmId, String variant) throws CertPathValidatorException { String sigAlgName = algorithmId.getName(); AlgorithmParameters sigAlgParams = algorithmId.getParameters(); certPathDefaultConstraints.permits(new ConstraintsParameters( sigAlgName, sigAlgParams, key, variant)); }
private static ObjectIdentifier mapPBEAlgorithmToOID(String algorithm) throws NoSuchAlgorithmException { // Check for PBES2 algorithms if (algorithm.toLowerCase(Locale.ENGLISH).startsWith("pbewithhmacsha")) { return pbes2_OID; } return AlgorithmId.get(algorithm).getOID(); }
public SignerInfo(X500Name issuerName, BigInteger serial, AlgorithmId digestAlgorithmId, AlgorithmId digestEncryptionAlgorithmId, byte[] encryptedDigest) { this.version = BigInteger.ONE; this.issuerName = issuerName; this.certificateSerialNumber = serial; this.digestAlgorithmId = digestAlgorithmId; this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId; this.encryptedDigest = encryptedDigest; }
MacData(String algName, byte[] digest, byte[] salt, int iterations) throws NoSuchAlgorithmException { if (algName == null) throw new NullPointerException("the algName parameter " + "must be non-null"); AlgorithmId algid = AlgorithmId.get(algName); this.digestAlgorithmName = algid.getName(); this.digestAlgorithmParams = algid.getParameters(); if (digest == null) { throw new NullPointerException("the digest " + "parameter must be non-null"); } else if (digest.length == 0) { throw new IllegalArgumentException("the digest " + "parameter must not be empty"); } else { this.digest = digest.clone(); } this.macSalt = salt; this.iterations = iterations; // delay the generation of ASN.1 encoding until // getEncoded() is called this.encoded = null; }
/** * Constructs a timestamp request for the supplied data. * * @param toBeTimeStamped The data to be timestamped. * @param messageDigest The MessageDigest of the hash algorithm to use. * @throws NoSuchAlgorithmException if the hash algorithm is not supported */ public TSRequest(String tSAPolicyID, byte[] toBeTimeStamped, MessageDigest messageDigest) throws NoSuchAlgorithmException { this.policyId = tSAPolicyID; this.hashAlgorithmId = AlgorithmId.get(messageDigest.getAlgorithm()); this.hashValue = messageDigest.digest(toBeTimeStamped); }
/** * Assembles a PKCS #7 signed data message that optionally includes a * signature timestamp. * * @param signature the signature bytes * @param signerChain the signer's X.509 certificate chain * @param content the content that is signed; specify null to not include * it in the PKCS7 data * @param signatureAlgorithm the name of the signature algorithm * @param tsaURI the URI of the Timestamping Authority; or null if no * timestamp is requested * @param tSAPolicyID the TSAPolicyID of the Timestamping Authority as a * numerical object identifier; or null if we leave the TSA server * to choose one. This argument is only used when tsaURI is provided * @return the bytes of the encoded PKCS #7 signed data message * @throws NoSuchAlgorithmException The exception is thrown if the signature * algorithm is unrecognised. * @throws CertificateException The exception is thrown if an error occurs * while processing the signer's certificate or the TSA's * certificate. * @throws IOException The exception is thrown if an error occurs while * generating the signature timestamp or while generating the signed * data message. */ public static byte[] generateSignedData(byte[] signature, X509Certificate[] signerChain, byte[] content, String signatureAlgorithm, URI tsaURI, String tSAPolicyID, String tSADigestAlg) throws CertificateException, IOException, NoSuchAlgorithmException { // Generate the timestamp token PKCS9Attributes unauthAttrs = null; if (tsaURI != null) { // Timestamp the signature HttpTimestamper tsa = new HttpTimestamper(tsaURI); byte[] tsToken = generateTimestampToken( tsa, tSAPolicyID, tSADigestAlg, signature); // Insert the timestamp token into the PKCS #7 signer info element // (as an unsigned attribute) unauthAttrs = new PKCS9Attributes(new PKCS9Attribute[]{ new PKCS9Attribute( PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_STR, tsToken)}); } // Create the SignerInfo X500Name issuerName = X500Name.asX500Name(signerChain[0].getIssuerX500Principal()); BigInteger serialNumber = signerChain[0].getSerialNumber(); String encAlg = AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm); String digAlg = AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm); SignerInfo signerInfo = new SignerInfo(issuerName, serialNumber, AlgorithmId.get(digAlg), null, AlgorithmId.get(encAlg), signature, unauthAttrs); // Create the PKCS #7 signed data message SignerInfo[] signerInfos = {signerInfo}; AlgorithmId[] algorithms = {signerInfo.getDigestAlgorithmId()}; // Include or exclude content ContentInfo contentInfo = (content == null) ? new ContentInfo(ContentInfo.DATA_OID, null) : new ContentInfo(content); PKCS7 pkcs7 = new PKCS7(algorithms, contentInfo, signerChain, signerInfos); ByteArrayOutputStream p7out = new ByteArrayOutputStream(); pkcs7.encodeSignedData(p7out); return p7out.toByteArray(); }
/** * Parses a PKCS#12 MAC data. */ MacData(DerInputStream derin) throws IOException, ParsingException { DerValue[] macData = derin.getSequence(2); // Parse the digest info DerInputStream digestIn = new DerInputStream(macData[0].toByteArray()); DerValue[] digestInfo = digestIn.getSequence(2); // Parse the DigestAlgorithmIdentifier. AlgorithmId digestAlgorithmId = AlgorithmId.parse(digestInfo[0]); this.digestAlgorithmName = digestAlgorithmId.getName(); this.digestAlgorithmParams = digestAlgorithmId.getParameters(); // Get the digest. this.digest = digestInfo[1].getOctetString(); // Get the salt. this.macSalt = macData[1].getOctetString(); // Iterations is optional. The default value is 1. if (macData.length > 2) { this.iterations = macData[2].getInteger(); } else { this.iterations = 1; } }
MacData(AlgorithmParameters algParams, byte[] digest, byte[] salt, int iterations) throws NoSuchAlgorithmException { if (algParams == null) throw new NullPointerException("the algParams parameter " + "must be non-null"); AlgorithmId algid = AlgorithmId.get(algParams); this.digestAlgorithmName = algid.getName(); this.digestAlgorithmParams = algid.getParameters(); if (digest == null) { throw new NullPointerException("the digest " + "parameter must be non-null"); } else if (digest.length == 0) { throw new IllegalArgumentException("the digest " + "parameter must not be empty"); } else { this.digest = digest.clone(); } this.macSalt = salt; this.iterations = iterations; // delay the generation of ASN.1 encoding until // getEncoded() is called this.encoded = null; }
/** * Returns the ASN.1 encoding of this object. * @return the ASN.1 encoding. * @exception IOException if error occurs when constructing its * ASN.1 encoding. */ public byte[] getEncoded() throws NoSuchAlgorithmException, IOException { if (this.encoded != null) return this.encoded.clone(); DerOutputStream out = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream(); DerOutputStream tmp2 = new DerOutputStream(); // encode encryption algorithm AlgorithmId algid = AlgorithmId.get(digestAlgorithmName); algid.encode(tmp2); // encode digest data tmp2.putOctetString(digest); tmp.write(DerValue.tag_Sequence, tmp2); // encode salt tmp.putOctetString(macSalt); // encode iterations tmp.putInteger(iterations); // wrap everything into a SEQUENCE out.write(DerValue.tag_Sequence, tmp); this.encoded = out.toByteArray(); return this.encoded.clone(); }
/** * Returns the name of the block file, ending with a block suffix * such as ".DSA". */ public String getBlockName() { String suffix = "DSA"; if (signatureBlock != null) { SignerInfo info = signatureBlock.getSignerInfos()[0]; suffix = info.getDigestEncryptionAlgorithmId().getName(); String temp = AlgorithmId.getEncAlgFromSigAlg(suffix); if (temp != null) suffix = temp; } return "META-INF/" + rawName + "." + suffix; }
/** * Constructs (i.e., parses) an <code>EncryptedPrivateKeyInfo</code> from * its ASN.1 encoding. * @param encoded the ASN.1 encoding of this object. The contents of * the array are copied to protect against subsequent modification. * @exception NullPointerException if the <code>encoded</code> is null. * @exception IOException if error occurs when parsing the ASN.1 encoding. */ public EncryptedPrivateKeyInfo(byte[] encoded) throws IOException { if (encoded == null) { throw new NullPointerException("the encoded parameter " + "must be non-null"); } this.encoded = encoded.clone(); DerValue val = new DerValue(this.encoded); DerValue[] seq = new DerValue[2]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); if (val.data.available() != 0) { throw new IOException("overrun, bytes = " + val.data.available()); } this.algid = AlgorithmId.parse(seq[0]); if (seq[0].data.available() != 0) { throw new IOException("encryptionAlgorithm field overrun"); } this.encryptedData = seq[1].getOctetString(); if (seq[1].data.available() != 0) { throw new IOException("encryptedData field overrun"); } }
/** * Returns the JCA {@link Signature} algorithm and {@code SignerInfo} {@code SignatureAlgorithm} * to use for {@code SignerInfo} which signs with the specified key and digest algorithms. */ @SuppressWarnings("restriction") private static Pair<String, AlgorithmId> getSignerInfoSignatureAlgorithm( PublicKey publicKey, DigestAlgorithm digestAlgorithm) throws InvalidKeyException { // NOTE: This method on purpose uses hard-coded OIDs instead of // Algorithm.getId(JCA Signature Algorithm). This is to ensure that the generated SignedData // is compatible with all targeted Android platforms and is not dependent on changes in the // JCA Signature Algorithm -> OID mappings maintained by AlgorithmId.get(String). String keyAlgorithm = publicKey.getAlgorithm(); String digestPrefixForSigAlg; switch (digestAlgorithm) { case SHA1: digestPrefixForSigAlg = "SHA1"; break; case SHA256: digestPrefixForSigAlg = "SHA256"; break; default: throw new IllegalArgumentException( "Unexpected digest algorithm: " + digestAlgorithm); } if ("RSA".equalsIgnoreCase(keyAlgorithm)) { return Pair.of( digestPrefixForSigAlg + "withRSA", getSupportedAlgorithmId("1.2.840.113549.1.1.1") // RSA encryption ); } else if ("DSA".equalsIgnoreCase(keyAlgorithm)) { AlgorithmId sigAlgId; switch (digestAlgorithm) { case SHA1: sigAlgId = getSupportedAlgorithmId("1.2.840.10040.4.1"); // DSA break; case SHA256: // DSA signatures with SHA-256 in SignedData are accepted by Android API Level // 21 and higher. However, there are two ways to specify their SignedData // SignatureAlgorithm: dsaWithSha256 (2.16.840.1.101.3.4.3.2) and // dsa (1.2.840.10040.4.1). The latter works only on API Level 22+. Thus, we use // the former. sigAlgId = getSupportedAlgorithmId("2.16.840.1.101.3.4.3.2"); // DSA with SHA-256 break; default: throw new IllegalArgumentException( "Unexpected digest algorithm: " + digestAlgorithm); } return Pair.of(digestPrefixForSigAlg + "withDSA", sigAlgId); } else if ("EC".equalsIgnoreCase(keyAlgorithm)) { return Pair.of( digestPrefixForSigAlg + "withECDSA", getSupportedAlgorithmId("1.2.840.10045.2.1") // EC public key ); } else { throw new InvalidKeyException("Unsupported key algorithm: " + keyAlgorithm); } }
/** * Returns the {@code SignerInfo} {@code DigestAlgorithm} to use for {@code SignerInfo} signing * using the specified digest algorithm. */ @SuppressWarnings("restriction") private static AlgorithmId getSignerInfoDigestAlgorithm(DigestAlgorithm digestAlgorithm) { switch (digestAlgorithm) { case SHA1: return OID_DIGEST_SHA1; case SHA256: return OID_DIGEST_SHA256; default: throw new RuntimeException("Unsupported digest algorithm: " + digestAlgorithm); } }
/** * Protects the given cleartext private key, using the password provided at * construction time. */ byte[] protect(PrivateKey key) throws Exception { // create a random salt (8 bytes) byte[] salt = new byte[8]; SunJCE.getRandom().nextBytes(salt); // create PBE parameters from salt and iteration count PBEParameterSpec pbeSpec = new PBEParameterSpec(salt, 20); // create PBE key from password PBEKeySpec pbeKeySpec = new PBEKeySpec(this.password); SecretKey sKey = new PBEKey(pbeKeySpec, "PBEWithMD5AndTripleDES"); pbeKeySpec.clearPassword(); // encrypt private key PBEWithMD5AndTripleDESCipher cipher; cipher = new PBEWithMD5AndTripleDESCipher(); cipher.engineInit(Cipher.ENCRYPT_MODE, sKey, pbeSpec, null); byte[] plain = key.getEncoded(); byte[] encrKey = cipher.engineDoFinal(plain, 0, plain.length); // wrap encrypted private key in EncryptedPrivateKeyInfo // (as defined in PKCS#8) AlgorithmParameters pbeParams = AlgorithmParameters.getInstance("PBE", SunJCE.getInstance()); pbeParams.init(pbeSpec); AlgorithmId encrAlg = new AlgorithmId (new ObjectIdentifier(PBE_WITH_MD5_AND_DES3_CBC_OID), pbeParams); return new EncryptedPrivateKeyInfo(encrAlg,encrKey).getEncoded(); }
/** * Parses an encoded, signed PKCS #10 certificate request, verifying * the request's signature as it does so. This constructor would * typically be used by a Certificate Authority, from which a new * certificate would then be constructed. * * @param data the DER-encoded PKCS #10 request. * @exception IOException for low level errors reading the data * @exception SignatureException when the signature is invalid * @exception NoSuchAlgorithmException when the signature * algorithm is not supported in this environment */ public PKCS10(byte[] data) throws IOException, SignatureException, NoSuchAlgorithmException { DerInputStream in; DerValue[] seq; AlgorithmId id; byte[] sigData; Signature sig; encoded = data; // // Outer sequence: request, signature algorithm, signature. // Parse, and prepare to verify later. // in = new DerInputStream(data); seq = in.getSequence(3); if (seq.length != 3) throw new IllegalArgumentException("not a PKCS #10 request"); data = seq[0].toByteArray(); // reusing this variable id = AlgorithmId.parse(seq[1]); sigData = seq[2].getBitString(); // // Inner sequence: version, name, key, attributes // BigInteger serial; DerValue val; serial = seq[0].data.getBigInteger(); if (!serial.equals(BigInteger.ZERO)) throw new IllegalArgumentException("not PKCS #10 v1"); subject = new X500Name(seq[0].data); subjectPublicKeyInfo = X509Key.parse(seq[0].data.getDerValue()); // Cope with a somewhat common illegal PKCS #10 format if (seq[0].data.available() != 0) attributeSet = new PKCS10Attributes(seq[0].data); else attributeSet = new PKCS10Attributes(); if (seq[0].data.available() != 0) throw new IllegalArgumentException("illegal PKCS #10 data"); // // OK, we parsed it all ... validate the signature using the // key and signature algorithm we found. // try { sig = Signature.getInstance(id.getName()); sig.initVerify(subjectPublicKeyInfo); sig.update(data); if (!sig.verify(sigData)) throw new SignatureException("Invalid PKCS #10 signature"); } catch (InvalidKeyException e) { throw new SignatureException("invalid key"); } }
private void parse(byte[] timestampTokenInfo) throws IOException { DerValue tstInfo = new DerValue(timestampTokenInfo); if (tstInfo.tag != DerValue.tag_Sequence) { throw new IOException("Bad encoding for timestamp token info"); } // Parse version version = tstInfo.data.getInteger(); // Parse policy policy = tstInfo.data.getOID(); // Parse messageImprint DerValue messageImprint = tstInfo.data.getDerValue(); hashAlgorithm = AlgorithmId.parse(messageImprint.data.getDerValue()); hashedMessage = messageImprint.data.getOctetString(); // Parse serialNumber serialNumber = tstInfo.data.getBigInteger(); // Parse genTime genTime = tstInfo.data.getGeneralizedTime(); // Parse optional elements, if present while (tstInfo.data.available() > 0) { DerValue d = tstInfo.data.getDerValue(); if (d.tag == DerValue.tag_Integer) { // must be the nonce nonce = d.getBigInteger(); break; } // Additional fields: // Parse accuracy // Parse ordering // Parse tsa // Parse extensions } }
public static void main(String[] args) throws Exception { byte[] data = "Hello".getBytes(); X500Name n = new X500Name("cn=Me"); CertAndKeyGen cakg = new CertAndKeyGen("RSA", "SHA256withRSA"); cakg.generate(1024); X509Certificate cert = cakg.getSelfCertificate(n, 1000); MessageDigest md = MessageDigest.getInstance("SHA-256"); PKCS9Attributes authed = new PKCS9Attributes(new PKCS9Attribute[]{ new PKCS9Attribute(PKCS9Attribute.CONTENT_TYPE_OID, ContentInfo.DATA_OID), new PKCS9Attribute(PKCS9Attribute.MESSAGE_DIGEST_OID, md.digest(data)), }); Signature s = Signature.getInstance("SHA256withRSA"); s.initSign(cakg.getPrivateKey()); s.update(authed.getDerEncoding()); byte[] sig = s.sign(); SignerInfo signerInfo = new SignerInfo( n, cert.getSerialNumber(), AlgorithmId.get("SHA-256"), authed, AlgorithmId.get("SHA256withRSA"), sig, null ); PKCS7 pkcs7 = new PKCS7( new AlgorithmId[] {signerInfo.getDigestAlgorithmId()}, new ContentInfo(data), new X509Certificate[] {cert}, new SignerInfo[] {signerInfo}); if (pkcs7.verify(signerInfo, data) == null) { throw new Exception("Not verified"); } }
/** * Check the signature algorithm with the specified public key. * * @param key the public key to verify the CRL signature * @param crl the target CRL */ static void check(PublicKey key, X509CRL crl) throws CertPathValidatorException { X509CRLImpl x509CRLImpl = null; try { x509CRLImpl = X509CRLImpl.toImpl(crl); } catch (CRLException ce) { throw new CertPathValidatorException(ce); } AlgorithmId algorithmId = x509CRLImpl.getSigAlgId(); check(key, algorithmId); }