Hi Jim, Please find below a short example that demonstrates how to append signature subpackets.
PGPSecretKeyRing certKey = ... String privateKeyPassword = ... PGPSignatureSubpacketGenerator hashed = new PGPSignatureSubpacketGenerator(); hashed.setSignatureCreationTime(false, new Date()); hashed.setRevocationReason(false, reason, description); PGPSignatureSubpacketGenerator unhashed = new PGPSignatureSubpacketGenerator(); unhashed.setIssuerKeyID(false, certKey.getPublicKey().getKeyID()); PGPSignatureGenerator sGen = new PGPSignatureGenerator(certKey.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1, PGPLib.BOUNCY_CASTLE_PROVIDER); sGen.initSign(PGPSignature.KEY_REVOCATION, certKey.getSecretKey().extractPrivateKey(privateKeyPassword.toCharArray(), "BC"); sGen.setHashedSubpackets(hashed.generate()); sGen.setUnhashedSubpackets(unhashed.generate()); Cheers, Atanas Krachev 2012/6/27 Jim Treinen <jtrei...@gmail.com> > Hi Atanas, > > Thank you very much for your advice on this topic. I am pretty new with > BouncyCastle, and I haven't had much luck getting this to work, do you > happen to have an example of creating hashed packets and adding them to the > output? > > I appreciate your help, and thanks again, > > Jim. > > > On Fri, Jun 15, 2012 at 3:38 AM, Atanas Krachev <akrac...@gmail.com>wrote: > >> Hi Jim, >> >> In theory a revocation certificate is a text file that you use in the >> case that you have lost either your private key or it's password >> to revoke your public key. >> >> The text file is a signature created just like you do it: >> sGen.InitSign(PgpSignature.KeyRevocation, pgpPrivKey); >> >> but you have to add additionally : >> 1. two hashed packets: CreationTime and RevocationReason >> 2. one unhashed packet : IssuerKeyID (in your case >> pgpSec.GetPublicKey().KeyId) >> >> the signature does not have to be updated (sGen.Update is useless) >> >> and there is one final thing: >> because ArmoredOutputStream has no way of producing correct revocation >> certificate headers >> you have to manually replace the generated ones with -----BEGIN PGP >> PUBLIC KEY BLOCK----- and -----END PGP PUBLIC KEY BLOCK----- >> >> In short that's it. >> >> Cheers, >> Atanas Krachev >> >> 2012/6/15 Jim Treinen <jtrei...@gmail.com> >> >>> Hello everyone, >>> >>> We are trying to create revocation certificates at key pair generation >>> time. We have the following code working, which works great for signing >>> and verifying challenge strings, however, when using it to create (what I >>> thought) were revocation certificates, it creates another detached >>> signature (adopted from the detached signature example), but the signature >>> does not verify as a valid revocation cert. >>> >>> The stringToSign being passed in, is the public key, and the boolean, >>> when set to true, is our attempt to generate a revocation cert. >>> >>> Thanks in advance, >>> >>> Jim T. >>> >>> >>> private string _createSignature(KeyModel keyModel, string stringToSign, >>> bool isRevocation) >>> >>> { >>> >>> >>> Stream outputStream; >>> >>> PgpSecretKey pgpSec; >>> >>> PgpPrivateKey pgpPrivKey; >>> >>> MemoryStream privateKeyStream; >>> >>> outputStream = new MemoryStream(); >>> >>> >>> ArmoredOutputStream armoredOutputStream >>> = new ArmoredOutputStream(outputStream); >>> >>> >>> byte[] toSignByteArray = Encoding.ASCII.GetBytes( >>> stringToSign ); >>> >>> MemoryStream toSignStream >>> = new MemoryStream(toSignByteArray); >>> >>> >>> // Get the private key >>> >>> using (InsecureByteArray iba >>> = new InsecureByteArray(KeyModel.PrivateKey, Encoding.ASCII)) >>> >>> { >>> >>> privateKeyStream = new MemoryStream(iba.Value); >>> >>> pgpSec = this.ReadSecretKey(privateKeyStream); >>> >>> privateKeyStream.Close(); >>> >>> } >>> >>> >>> >>> using (InsecureCharArray ica >>> = new InsecureCharArray(KeyModel.Passphrase)) >>> >>> { >>> >>> pgpPrivKey = pgpSec.ExtractPrivateKey(ica.Value); >>> >>> } >>> >>> >>> PgpSignatureGenerator sGen >>> = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, >>> HashAlgorithmTag.Sha256); >>> >>> if (isRevocation) >>> >>> { >>> >>> sGen.InitSign(PgpSignature.KeyRevocation, pgpPrivKey); >>> >>> } >>> >>> else >>> >>> { >>> >>> sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey); >>> >>> } >>> >>> >>> BcpgOutputStream bOut >>> = new BcpgOutputStream(armoredOutputStream); >>> >>> >>> >>> int ch = 0; >>> >>> while ((ch = toSignStream.ReadByte()) >= 0) >>> >>> { >>> >>> // lOut.WriteByte((byte)ch); >>> >>> sGen.Update((byte)ch); >>> >>> } >>> >>> >>> >>> >>> // send the signature to the output stream >>> >>> sGen.Generate().Encode(bOut); >>> >>> >>> // Clean up >>> >>> bOut.Close(); // BcpgOutputStream >>> >>> toSignStream.Close(); // input file stream >>> >>> >>> outputStream.Position = 0; >>> >>> StreamReader reader = new StreamReader(outputStream); >>> >>> string signature = reader.ReadToEnd(); >>> >>> >>> armoredOutputStream.Close(); // armored stream >>> >>> outputStream.Close(); // underlying stream >>> >>> >>> >>> reader.Close(); >>> >>> >>> return signature; >>> >>> >>> } >>> >> >> >