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 <[email protected]>
> 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 <[email protected]>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 <[email protected]>
>>
>>> 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;
>>>
>>>
>>> }
>>>
>>
>>
>