protected void processCertificateVerify( ServerHandshakeState state, byte[] body, TlsHandshakeHash prepareFinishHash) throws IOException { ByteArrayInputStream buf = new ByteArrayInputStream(body); DigitallySigned clientCertificateVerify = DigitallySigned.parse(state.serverContext, buf); TlsProtocol.assertEmpty(buf); // Verify the CertificateVerify message contains a correct signature. try { // TODO For TLS 1.2, this needs to be the hash specified in the DigitallySigned byte[] certificateVerifyHash = TlsProtocol.getCurrentPRFHash(state.serverContext, prepareFinishHash, null); org.bouncycastle.asn1.x509.Certificate x509Cert = state.clientCertificate.getCertificateAt(0); SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); AsymmetricKeyParameter publicKey = PublicKeyFactory.createKey(keyInfo); TlsSigner tlsSigner = TlsUtils.createTlsSigner(state.clientCertificateType); tlsSigner.init(state.serverContext); tlsSigner.verifyRawSignature( clientCertificateVerify.getAlgorithm(), clientCertificateVerify.getSignature(), publicKey, certificateVerifyHash); } catch (Exception e) { throw new TlsFatalAlert(AlertDescription.decrypt_error); } }
public void processServerCertificate(Certificate serverCertificate) throws IOException { X509CertificateStructure x509Cert = serverCertificate.certs[0]; SubjectPublicKeyInfo keyInfo = x509Cert.getSubjectPublicKeyInfo(); try { this.serverPublicKey = PublicKeyFactory.createKey(keyInfo); } catch (RuntimeException e) { throw new TlsFatalAlert(AlertDescription.unsupported_certificate); } if (tlsSigner == null) { try { this.dhAgreeServerPublicKey = validateDHPublicKey((DHPublicKeyParameters) this.serverPublicKey); } catch (ClassCastException e) { throw new TlsFatalAlert(AlertDescription.certificate_unknown); } TlsUtils.validateKeyUsage(x509Cert, KeyUsage.keyAgreement); } else { if (!tlsSigner.isValidPublicKey(this.serverPublicKey)) { throw new TlsFatalAlert(AlertDescription.certificate_unknown); } TlsUtils.validateKeyUsage(x509Cert, KeyUsage.digitalSignature); } // TODO /* * Perform various checks per RFC2246 7.4.2: "Unless otherwise specified, the * signing algorithm for the certificate must be the same as the algorithm for the * certificate key." */ }
/** * Extracts the <tt>PublicKey</tt> from the provided CSR. * * <p>This method will throw a {@link RuntimeException} if the JRE is missing the RSA algorithm, * which is a required algorithm as defined by the JCA. * * @param csr the CSR to extract from. * @return the extracted <tt>PublicKey</tt> * @throws InvalidKeySpecException if the CSR is not using an RSA key. * @throws IOException if there is an error extracting the <tt>PublicKey</tt> parameters. */ public static PublicKey getPublicKey(final PKCS10CertificationRequest csr) throws InvalidKeySpecException, IOException { SubjectPublicKeyInfo pubKeyInfo = csr.getSubjectPublicKeyInfo(); RSAKeyParameters keyParams = (RSAKeyParameters) PublicKeyFactory.createKey(pubKeyInfo); KeySpec keySpec = new RSAPublicKeySpec(keyParams.getModulus(), keyParams.getExponent()); KeyFactory kf; try { kf = KeyFactory.getInstance("RSA"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } return kf.generatePublic(keySpec); }
public static void testGenP12() throws Exception { String rootCerBase64 = "MIIDvTCCAqWgAwIBAgIEEioP6zANBgkqhkiG9w0BAQsFADCBjjELMAkGA1UEBhMC" + "Q04xETAPBgNVBAgTCHNoYW5naGFpMREwDwYDVQQHEwhzaGFuZ2hhaTEzMDEGA1UE" + "Cgwq5LiK5rW36YeR6bm/6YeR6J6N5L+h5oGv5pyN5Yqh5pyJ6ZmQ5YWs5Y+4MQsw" + "CQYDVQQLEwJJVDEXMBUGA1UEAxMOb3Blbi5qbGZleC5jb20wHhcNMTQwODIxMDM0" + "NTQ5WhcNMjQwODE4MDM0NTQ5WjCBjjELMAkGA1UEBhMCQ04xETAPBgNVBAgTCHNo" + "YW5naGFpMREwDwYDVQQHEwhzaGFuZ2hhaTEzMDEGA1UECgwq5LiK5rW36YeR6bm/" + "6YeR6J6N5L+h5oGv5pyN5Yqh5pyJ6ZmQ5YWs5Y+4MQswCQYDVQQLEwJJVDEXMBUG" + "A1UEAxMOb3Blbi5qbGZleC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK" + "AoIBAQCQ4q4Yh8EPHbAP+BMiystXOEV56OE+IUwxSS7fRZ3ZrIEPImpnCiAe1txZ" + "vk0Lgv8ZWqrj4ErOT5FoOWfQW6Vva1DOXknCzFbypJMjqVnIS1/OwB64sYg4naLc" + "mM95GAHtEv9qxIWLbPhoLShz54znRNbM7mZJyT4BwLhKuKmfdo3UEuXvcoUFLN2l" + "f2wiTNmgMgpxcnCsWAx2nJaonPGCVXeQu0PXCVmCTyUUCWdT7P1io5yEpuRP/Dac" + "//g7Em8rkulgeO7e3gnEbrgrczsr2H1KJLTBjQmyWeWZg7LRYML6oHODrrDb0x++" + "yDT01p2BJHlvw/UzJq3I/CCci0lFAgMBAAGjITAfMB0GA1UdDgQWBBS1Lo57VqvU" + "BnfyJu51JO9csLJenjANBgkqhkiG9w0BAQsFAAOCAQEACcfPaVl5PIkBZ6cXyHuj" + "rJZkZH7Koqhx12DNeCoohdQkRda/gWeHVPsO7snK63sFhoY08OGVgvTRhgzwSBxJ" + "cx9GkCyojfHo5xZoOlSQ01PygyScd42DlseNiwXZGBfoxacLEYkIP6OXrDa+wNAP" + "gHnLI+37tzkafoPT0xoV/E9thvUUKX1jSIL5UCoGuso6FWLiZgDxD8wKgd22FcYo" + "T7B7DHG4R+0rgav81J9xjgOR3ayvNrb86iVvVBmrIiM7Gc2hf5PMiiAOaISST2cJ" + "x90X7TUA/f0qrYKveTvkRT77nLfzHV1a+PTS7PwkCXUt/NRm4VwseyGIgQ4FXH6W" + "zw=="; // 解析root CA 证书 X509Certificate rootcaCertificate = CertificateCoder.getX509Certificate(Base64.decodeBase64(rootCerBase64)); // 解析root CA 私钥 String rootcaDer = FileUtils.readFileToString(new File("d:\\rootcakey.pem"), "UTF-8"); PrivateKey rootcaPrivateKey = PKCSCertificateCoder.getPrivateKeyFromPem(rootcaDer, ""); System.out.println(rootcaPrivateKey); // 1.生成用户密钥对 Security.addProvider(new BouncyCastleProvider()); KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC"); kpg.initialize(2048); KeyPair kp = kpg.genKeyPair(); // 2.生成用户证书请求 PKCS10CertificationRequest p10 = genPKCS10(kp); SubjectPublicKeyInfo subPublicKeyInfo = p10.getSubjectPublicKeyInfo(); RSAKeyParameters rsa = (RSAKeyParameters) PublicKeyFactory.createKey(subPublicKeyInfo); RSAPublicKeySpec rsaSpec = new RSAPublicKeySpec(rsa.getModulus(), rsa.getExponent()); KeyFactory kf = KeyFactory.getInstance("RSA"); PublicKey publicKey = kf.generatePublic(rsaSpec); // 3.生成用户证书 X509Certificate clientCertificate = buildEndEntityCert(publicKey, rootcaPrivateKey, rootcaCertificate); FileUtils.writeByteArrayToFile(new File("d:\\client.cer"), clientCertificate.getEncoded()); // 4.生成用户p12文件 storeP12( kp, new X509Certificate[] {clientCertificate, rootcaCertificate}, "d:\\client.p12", "123456"); FileOutputStream fos = new FileOutputStream(new File("d:\\client1.p12")); X509Certificate[] chain = new X509Certificate[] {rootcaCertificate, clientCertificate, clientCertificate}; genPKCS12File(fos, kp.getPrivate(), chain); }