Generating PGP keys compatible with PGP Desktop using BouncyCastle

This is just a note to remind myself on how to do this in the future…
Like the title suggested, all I want to do is to generate key pairs (using BouncyCastle library) that can be used for encryption in PGP Desktop. This takes a while to figure out because one very crucial information is being hidden by BouncyCastle. I have to google for 2 days to dig out this info – this very important link that they decided not to put in their FAQ: http://www.bouncycastle.org/wiki/display/JA1/PGP+Questions

Apparently for later version of PGP Desktop, if you generate an RSA key without a subkey, you can only use it for signing, and not for encryption (read this).

So, we start off like usual…

       
// add provider
Security.addProvider(new BouncyCastleProvider());

// get keypair generator
//parameter 1: key type algorithm =  RSA, DSA
//parameter 2: provider = BC (BouncyCastle)
KeyPairGenerator  keyPairGen = KeyPairGenerator.getInstance("RSA", "BC");        \

// specify key size
// encryption key size: 1024-4096
keyPairGen.initialize(2048);

// generate key pair
KeyPair keyPair = keyPairGen.generateKeyPair();

Then comes the tricky bit where you have to generate hashed subpackets…


PGPSignatureSubpacketGenerator    hashedGen = new PGPSignatureSubpacketGenerator();

hashedGen.setKeyFlags(true, KeyFlags.ENCRYPT_STORAGE);
hashedGen.setPreferredCompressionAlgorithms(false, 
    new int[] { CompressionAlgorithmTags.ZLIB, 
                    CompressionAlgorithmTags.ZIP});

hashedGen.setPreferredHashAlgorithms(false,  
    new int[] { HashAlgorithmTags.SHA256,
                    HashAlgorithmTags.SHA384, 
                    HashAlgorithmTags.SHA512} );

hashedGen.setPreferredSymmetricAlgorithms(false, 
    new int[] { SymmetricKeyAlgorithmTags.AES_256, 
                    SymmetricKeyAlgorithmTags.AES_192, 
                    SymmetricKeyAlgorithmTags.AES_128, 
                    SymmetricKeyAlgorithmTags.CAST5, 
                    SymmetricKeyAlgorithmTags.DES});

//add hashed subpacket to secret key 
PGPSecretKey    secretKey = new PGPSecretKey(
	PGPSignature.DEFAULT_CERTIFICATION, 	//certificationLevel
	PublicKeyAlgorithmTags.RSA_GENERAL, 	//algorithm
	publicKey, 		//java.security.PublicKey
	privateKey, 	//java.security.PrivateKey
	new Date(), 	//time
	identity, 		//id
	SymmetricKeyAlgorithmTags.AES_256, 	//encAlgorithm: AES_128, AES_192, AES_256, BLOWFISH, CAST5, DES, IDEA, NULL, SAFER, TRIPLE_DES, TWOFISH         
	passPhrase, 		//passPhrase
	hashedGen.generate(),	//hashedPcks 	PGPSignatureSubpacketVector
	null, 				//unhashedPcks	PGPSignatureSubpacketVector
	new SecureRandom(), 	//java.security.SecureRandom
	"BC");				//provider

This will produce key with selected Hash, Cipher and Compression in PGP Desktop :

From Work Screen Caps