@SuppressWarnings("deprecation") static PGPPublicKey loadPublicKey(ByteSource pgpPublicKeyFile) { try (InputStream input = pgpPublicKeyFile.openStream(); InputStream decoder = PGPUtil.getDecoderStream(input)) { return new BcPGPPublicKeyRing(decoder).getPublicKey(); } catch (IOException e) { throw new RuntimeException(e); } }
/** Returns raw key bytes as a Bouncy Castle PGP public key. */ public static PGPPublicKey loadPublicKeyBytes(byte[] data) { try { return lookupPublicSubkey(new BcPGPPublicKeyRing(data), KeyRequirement.ENCRYPT).get(); } catch (IOException e) { throw new RuntimeException(e); } }
/** Deserialize a PGPPublicKey */ public static PGPPublicKey deserializePublicKey(byte[] serialized) throws IOException { return new BcPGPPublicKeyRing( PGPUtil.getDecoderStream( new ByteArrayInputStream(serialized))).getPublicKey(); }
@Test public void testSignVerify_Detached() throws Exception { // Load the keys. PGPPublicKeyRing publicKeyRing = new BcPGPPublicKeyRing(PUBLIC_KEY); PGPSecretKeyRing privateKeyRing = new BcPGPSecretKeyRing(PRIVATE_KEY); PGPPublicKey publicKey = publicKeyRing.getPublicKey(); PGPPrivateKey privateKey = extractPrivateKey(privateKeyRing.getSecretKey()); // Sign the data and write signature data to "signatureFile". // Note: RSA_GENERAL will encrypt AND sign. RSA_SIGN and RSA_ENCRYPT are deprecated. PGPSignatureGenerator signer = new PGPSignatureGenerator( new BcPGPContentSignerBuilder(RSA_GENERAL, SHA256)); signer.init(PGPSignature.BINARY_DOCUMENT, privateKey); addUserInfoToSignature(publicKey, signer); signer.update(FALL_OF_HYPERION_A_DREAM.getBytes(UTF_8)); ByteArrayOutputStream output = new ByteArrayOutputStream(); signer.generate().encode(output); byte[] signatureFileData = output.toByteArray(); logger.info(".sig file data: " + dumpHex(signatureFileData)); // Load algorithm information and signature data from "signatureFileData". PGPSignature sig; try (ByteArrayInputStream input = new ByteArrayInputStream(signatureFileData)) { PGPObjectFactory pgpFact = new BcPGPObjectFactory(input); PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); assertThat(sigList.size()).isEqualTo(1); sig = sigList.get(0); } // Use "onePass" and "sig" to verify "publicKey" signed the text. sig.init(new BcPGPContentVerifierBuilderProvider(), publicKey); sig.update(FALL_OF_HYPERION_A_DREAM.getBytes(UTF_8)); assertThat(sig.verify()).isTrue(); // Verify that they DIDN'T sign the text "hello monster". sig.init(new BcPGPContentVerifierBuilderProvider(), publicKey); sig.update("hello monster".getBytes(UTF_8)); assertThat(sig.verify()).isFalse(); }
@Test public void testEncryptDecrypt_ExplicitStyle() throws Exception { int bufferSize = 64 * 1024; // Alice loads Bob's "publicKey" into memory. PGPPublicKeyRing publicKeyRing = new BcPGPPublicKeyRing(PUBLIC_KEY); PGPPublicKey publicKey = publicKeyRing.getPublicKey(); // Alice encrypts the secret message for Bob using his "publicKey". PGPEncryptedDataGenerator encryptor = new PGPEncryptedDataGenerator( new BcPGPDataEncryptorBuilder(AES_128)); encryptor.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(publicKey)); byte[] encryptedData; try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { try (OutputStream output2 = encryptor.open(output, new byte[bufferSize])) { output2.write(FALL_OF_HYPERION_A_DREAM.getBytes(UTF_8)); } encryptedData = output.toByteArray(); } logger.info("Encrypted data: " + dumpHex(encryptedData)); // Bob loads his "privateKey" into memory. PGPSecretKeyRing privateKeyRing = new BcPGPSecretKeyRing(PRIVATE_KEY); PGPPrivateKey privateKey = extractPrivateKey(privateKeyRing.getSecretKey()); // Bob decrypt's the OpenPGP message (w/ ciphertext) using his "privateKey". try (ByteArrayInputStream input = new ByteArrayInputStream(encryptedData)) { PGPObjectFactory pgpFact = new BcPGPObjectFactory(input); PGPEncryptedDataList encDataList = (PGPEncryptedDataList) pgpFact.nextObject(); assertThat(encDataList.size()).isEqualTo(1); PGPPublicKeyEncryptedData encData = (PGPPublicKeyEncryptedData) encDataList.get(0); assertThat(encData.getKeyID()).isEqualTo(publicKey.getKeyID()); assertThat(encData.getKeyID()).isEqualTo(privateKey.getKeyID()); try (InputStream original = encData.getDataStream(new BcPublicKeyDataDecryptorFactory(privateKey))) { assertThat(CharStreams.toString(new InputStreamReader(original, UTF_8))) .isEqualTo(FALL_OF_HYPERION_A_DREAM); } } }
@Test public void testSignVerify_OnePass() throws Exception { // Load the keys. PGPPublicKeyRing publicKeyRing = new BcPGPPublicKeyRing(PUBLIC_KEY); PGPSecretKeyRing privateKeyRing = new BcPGPSecretKeyRing(PRIVATE_KEY); PGPPublicKey publicKey = publicKeyRing.getPublicKey(); PGPPrivateKey privateKey = extractPrivateKey(privateKeyRing.getSecretKey()); // Sign the data and write signature data to "signatureFile". PGPSignatureGenerator signer = new PGPSignatureGenerator( new BcPGPContentSignerBuilder(RSA_GENERAL, SHA256)); signer.init(PGPSignature.BINARY_DOCUMENT, privateKey); addUserInfoToSignature(publicKey, signer); ByteArrayOutputStream output = new ByteArrayOutputStream(); signer.generateOnePassVersion(false).encode(output); signer.update(FALL_OF_HYPERION_A_DREAM.getBytes(UTF_8)); signer.generate().encode(output); byte[] signatureFileData = output.toByteArray(); logger.info(".sig file data: " + dumpHex(signatureFileData)); // Load algorithm information and signature data from "signatureFileData". PGPSignature sig; PGPOnePassSignature onePass; try (ByteArrayInputStream input = new ByteArrayInputStream(signatureFileData)) { PGPObjectFactory pgpFact = new BcPGPObjectFactory(input); PGPOnePassSignatureList onePassList = (PGPOnePassSignatureList) pgpFact.nextObject(); PGPSignatureList sigList = (PGPSignatureList) pgpFact.nextObject(); assertThat(onePassList.size()).isEqualTo(1); assertThat(sigList.size()).isEqualTo(1); onePass = onePassList.get(0); sig = sigList.get(0); } // Use "onePass" and "sig" to verify "publicKey" signed the text. onePass.init(new BcPGPContentVerifierBuilderProvider(), publicKey); onePass.update(FALL_OF_HYPERION_A_DREAM.getBytes(UTF_8)); assertThat(onePass.verify(sig)).isTrue(); // Verify that they DIDN'T sign the text "hello monster". onePass.init(new BcPGPContentVerifierBuilderProvider(), publicKey); onePass.update("hello monster".getBytes(UTF_8)); assertThat(onePass.verify(sig)).isFalse(); }
/** Creates a {@link PersonalKey} from private keyring data. */ @SuppressWarnings("unchecked") public static PersonalKey load(byte[] privateKeyData, char[] passphrase, byte[] bridgeCertData) throws KonException, IOException, PGPException, CertificateException, NoSuchProviderException { PGPSecretKeyRing secRing = new PGPSecretKeyRing(privateKeyData, PGPUtils.FP_CALC); PGPSecretKey authKey = null; PGPSecretKey signKey = null; PGPSecretKey encrKey = null; // assign from key ring Iterator<PGPSecretKey> skeys = secRing.getSecretKeys(); while (skeys.hasNext()) { PGPSecretKey key = skeys.next(); if (key.isMasterKey()) { // master key: authentication / legacy: signing authKey = key; } else if (PGPUtils.isSigningKey(key.getPublicKey())) { // sub keys: encryption and signing / legacy: only encryption signKey = key; } else if (key.getPublicKey().isEncryptionKey()) { encrKey = key; } } // legacy: auth key is actually signing key if (signKey == null && authKey != null && authKey.isSigningKey()) { LOGGER.info("legacy key"); signKey = authKey; } if (authKey == null || signKey == null || encrKey == null) { LOGGER.warning("something could not be found, " +"sign="+signKey+ ", auth="+authKey+", encr="+encrKey); throw new KonException(KonException.Error.LOAD_KEY, new PGPException("could not find all keys in key data")); } // decrypt private keys PBESecretKeyDecryptor decryptor = new JcePBESecretKeyDecryptorBuilder() .setProvider(PGPUtils.PROVIDER) .build(passphrase); PGPKeyPair authKeyPair = PGPUtils.decrypt(authKey, decryptor); PGPKeyPair signKeyPair = PGPUtils.decrypt(signKey, decryptor); PGPKeyPair encryptKeyPair = PGPUtils.decrypt(encrKey, decryptor); // user ID Iterator<?> uidIt = authKey.getUserIDs(); if (!uidIt.hasNext()) throw new KonException(KonException.Error.LOAD_KEY, new PGPException("no UID in key")); String uid = (String) uidIt.next(); // X.509 bridge certificate X509Certificate bridgeCert; if (bridgeCertData != null) { bridgeCert = PGPUtils.loadX509Cert(bridgeCertData); } else { // public key ring ByteArrayOutputStream out = new ByteArrayOutputStream(); authKeyPair.getPublicKey().encode(out); signKeyPair.getPublicKey().encode(out); encryptKeyPair.getPublicKey().encode(out); byte[] publicKeyRingData = out.toByteArray(); PGPPublicKeyRing pubKeyRing = new BcPGPPublicKeyRing(publicKeyRingData); // re-create cert bridgeCert = createX509Certificate(authKeyPair, pubKeyRing); } return new PersonalKey(authKeyPair, signKeyPair, encryptKeyPair, bridgeCert, uid); }