PGPUtil.setDefaultProvider("BC");
//
// Read the public key
//
PGPObjectFactory pgpFact = new PGPObjectFactory(testPubKeyRing);
PGPPublicKeyRing pgpPub = (PGPPublicKeyRing)pgpFact.nextObject();
pubKey = pgpPub.getPublicKey();
if (pubKey.getBitStrength() != 1024)
{
fail("failed - key strength reported incorrectly.");
}
//
// Read the private key
//
PGPSecretKeyRing sKey = new PGPSecretKeyRing(testPrivKeyRing, new BcKeyFingerprintCalculator());
PGPPrivateKey pgpPrivKey = sKey.getSecretKey().extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass));
//
// signature generation
//
String data = "hello world!";
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
ByteArrayInputStream testIn = new ByteArrayInputStream(data.getBytes());
PGPSignatureGenerator sGen = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(PGPPublicKey.DSA, PGPUtil.SHA1));
sGen.init(PGPSignature.BINARY_DOCUMENT, pgpPrivKey);
PGPCompressedDataGenerator cGen = new PGPCompressedDataGenerator(
PGPCompressedData.ZIP);
BCPGOutputStream bcOut = new BCPGOutputStream(
cGen.open(new UncloseableOutputStream(bOut)));
sGen.generateOnePassVersion(false).encode(bcOut);
PGPLiteralDataGenerator lGen = new PGPLiteralDataGenerator();
Date testDate = new Date((System.currentTimeMillis() / 1000) * 1000);
OutputStream lOut = lGen.open(
new UncloseableOutputStream(bcOut),
PGPLiteralData.BINARY,
"_CONSOLE",
data.getBytes().length,
testDate);
int ch;
while ((ch = testIn.read()) >= 0)
{
lOut.write(ch);
sGen.update((byte)ch);
}
lGen.close();
sGen.generate().encode(bcOut);
cGen.close();
//
// verify generated signature
//
pgpFact = new PGPObjectFactory(bOut.toByteArray());
PGPCompressedData c1 = (PGPCompressedData)pgpFact.nextObject();
pgpFact = new PGPObjectFactory(c1.getDataStream());
PGPOnePassSignatureList p1 = (PGPOnePassSignatureList)pgpFact.nextObject();
PGPOnePassSignature ops = p1.get(0);
PGPLiteralData p2 = (PGPLiteralData)pgpFact.nextObject();
if (!p2.getModificationTime().equals(testDate))
{
fail("Modification time not preserved");
}
InputStream dIn = p2.getInputStream();
ops.init(new BcPGPContentVerifierBuilderProvider(), pubKey);
while ((ch = dIn.read()) >= 0)
{
ops.update((byte)ch);
}
PGPSignatureList p3 = (PGPSignatureList)pgpFact.nextObject();
if (!ops.verify(p3.get(0)))
{
fail("Failed generated signature check");
}
//
// test encryption
//
//
// find a key suitable for encryption
//
long pgpKeyID = 0;
AsymmetricKeyParameter pKey = null;
BcPGPKeyConverter keyConverter = new BcPGPKeyConverter();
Iterator it = pgpPub.getPublicKeys();
while (it.hasNext())
{
PGPPublicKey pgpKey = (PGPPublicKey)it.next();
if (pgpKey.getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT
|| pgpKey.getAlgorithm() == PGPPublicKey.ELGAMAL_GENERAL)
{
pKey = keyConverter.getPublicKey(pgpKey);
pgpKeyID = pgpKey.getKeyID();
if (pgpKey.getBitStrength() != 1024)
{
fail("failed - key strength reported incorrectly.");
}
//
// verify the key
//
}
}
AsymmetricBlockCipher c = new PKCS1Encoding(new ElGamalEngine());
c.init(true, pKey);
byte[] in = "hello world".getBytes();
byte[] out = c.processBlock(in, 0, in.length);
pgpPrivKey = sKey.getSecretKey(pgpKeyID).extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass));
c.init(false, keyConverter.getPrivateKey(pgpPrivKey));
out = c.processBlock(out, 0, out.length);
if (!areEqual(in, out))
{
fail("decryption failed.");
}
//
// encrypted message
//
byte[] text = { (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o', (byte)' ', (byte)'w', (byte)'o', (byte)'r', (byte)'l', (byte)'d', (byte)'!', (byte)'\n' };
PGPObjectFactory pgpF = new PGPObjectFactory(encMessage);
PGPEncryptedDataList encList = (PGPEncryptedDataList)pgpF.nextObject();
PGPPublicKeyEncryptedData encP = (PGPPublicKeyEncryptedData)encList.get(0);
InputStream clear = encP.getDataStream(new BcPublicKeyDataDecryptorFactory(pgpPrivKey));
pgpFact = new PGPObjectFactory(clear);
c1 = (PGPCompressedData)pgpFact.nextObject();
pgpFact = new PGPObjectFactory(c1.getDataStream());
PGPLiteralData ld = (PGPLiteralData)pgpFact.nextObject();
bOut = new ByteArrayOutputStream();
if (!ld.getFileName().equals("test.txt"))
{
throw new RuntimeException("wrong filename in packet");
}
InputStream inLd = ld.getDataStream();
while ((ch = inLd.read()) >= 0)
{
bOut.write(ch);
}
if (!areEqual(bOut.toByteArray(), text))
{
fail("wrong plain text in decrypted packet");
}
//
// signed and encrypted message
//
pgpF = new PGPObjectFactory(signedAndEncMessage);
encList = (PGPEncryptedDataList)pgpF.nextObject();
encP = (PGPPublicKeyEncryptedData)encList.get(0);
clear = encP.getDataStream(new BcPublicKeyDataDecryptorFactory(pgpPrivKey));
pgpFact = new PGPObjectFactory(clear);
c1 = (PGPCompressedData)pgpFact.nextObject();
pgpFact = new PGPObjectFactory(c1.getDataStream());
p1 = (PGPOnePassSignatureList)pgpFact.nextObject();
ops = p1.get(0);
ld = (PGPLiteralData)pgpFact.nextObject();
bOut = new ByteArrayOutputStream();
if (!ld.getFileName().equals("test.txt"))
{
throw new RuntimeException("wrong filename in packet");
}
inLd = ld.getDataStream();
//
// note: we use the DSA public key here.
//
ops.init(new BcPGPContentVerifierBuilderProvider(), pgpPub.getPublicKey());
while ((ch = inLd.read()) >= 0)
{
ops.update((byte)ch);
bOut.write(ch);
}
p3 = (PGPSignatureList)pgpFact.nextObject();
if (!ops.verify(p3.get(0)))
{
fail("Failed signature check");
}
if (!areEqual(bOut.toByteArray(), text))
{
fail("wrong plain text in decrypted packet");
}
//
// encrypt
//
ByteArrayOutputStream cbOut = new ByteArrayOutputStream();
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.TRIPLE_DES).setSecureRandom(new SecureRandom()));
PGPPublicKey puK = sKey.getSecretKey(pgpKeyID).getPublicKey();
cPk.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(puK));
OutputStream cOut = cPk.open(new UncloseableOutputStream(cbOut), bOut.toByteArray().length);
cOut.write(text);
cOut.close();
pgpF = new PGPObjectFactory(cbOut.toByteArray());
encList = (PGPEncryptedDataList)pgpF.nextObject();
encP = (PGPPublicKeyEncryptedData)encList.get(0);
pgpPrivKey = sKey.getSecretKey(pgpKeyID).extractPrivateKey(new BcPBESecretKeyDecryptorBuilder(new BcPGPDigestCalculatorProvider()).build(pass));
clear = encP.getDataStream(new BcPublicKeyDataDecryptorFactory(pgpPrivKey));
bOut.reset();
while ((ch = clear.read()) >= 0)
{
bOut.write(ch);
}
out = bOut.toByteArray();
if (!areEqual(out, text))
{
fail("wrong plain text in generated packet");
}
//
// use of PGPKeyPair
//
BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ElGamal", "BC");
ElGamalParameterSpec elParams = new ElGamalParameterSpec(p, g);
kpg.initialize(elParams);
KeyPair kp = kpg.generateKeyPair();
PGPKeyPair pgpKp = new PGPKeyPair(PGPPublicKey.ELGAMAL_GENERAL , kp.getPublic(), kp.getPrivate(), new Date());
PGPPublicKey k1 = pgpKp.getPublicKey();
PGPPrivateKey k2 = pgpKp.getPrivateKey();
// Test bug with ElGamal P size != 0 mod 8 (don't use these sizes at home!)
SecureRandom random = new SecureRandom();
for (int pSize = 257; pSize < 264; ++pSize)
{
// Generate some parameters of the given size
AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("ElGamal", "BC");
a.init(pSize, new SecureRandom());
AlgorithmParameters params = a.generateParameters();
DHParameterSpec elP = (DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("ElGamal", "BC");
keyGen.initialize(elP);
// Run a short encrypt/decrypt test with random key for the given parameters
kp = keyGen.generateKeyPair();
PGPKeyPair elGamalKeyPair = new PGPKeyPair(
PublicKeyAlgorithmTags.ELGAMAL_GENERAL, kp, new Date());
cPk = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.CAST5).setSecureRandom(random));
puK = elGamalKeyPair.getPublicKey();
cPk.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(puK));
cbOut = new ByteArrayOutputStream();
cOut = cPk.open(cbOut, text.length);
cOut.write(text);
cOut.close();
pgpF = new PGPObjectFactory(cbOut.toByteArray());
encList = (PGPEncryptedDataList)pgpF.nextObject();
encP = (PGPPublicKeyEncryptedData)encList.get(0);
pgpPrivKey = elGamalKeyPair.getPrivateKey();
// Note: This is where an exception would be expected if the P size causes problems
clear = encP.getDataStream(new BcPublicKeyDataDecryptorFactory(pgpPrivKey));
ByteArrayOutputStream dec = new ByteArrayOutputStream();
int b;
while ((b = clear.read()) >= 0)
{
dec.write(b);
}
byte[] decText = dec.toByteArray();
if (!areEqual(text, decText))
{
fail("decrypted message incorrect");
}
}
// check sub key encoding
it = pgpPub.getPublicKeys();
while (it.hasNext())
{
PGPPublicKey pgpKey = (PGPPublicKey)it.next();
if (!pgpKey.isMasterKey())
{
byte[] kEnc = pgpKey.getEncoded();
PGPObjectFactory objF = new PGPObjectFactory(kEnc);
PGPPublicKey k = (PGPPublicKey)objF.nextObject();
pKey = keyConverter.getPublicKey(k);
pgpKeyID = k.getKeyID();
if (k.getBitStrength() != 1024)
{
fail("failed - key strength reported incorrectly.");
}
if (objF.nextObject() != null)
{
fail("failed - stream not fully parsed.");
}
}
}