Good morning Atanas,

Thank you for your help, I have attempted to incorporate the solution you
provided to construct detached revocation certificates.

Unfortunately, the C# library doesn't appear to have an equivalent to

hashed.setRevocationReason(false, reason, description);

I have incorporated everything else, and the revocation certificate
verification still fails. I am guessing that that this is due to the lack
of revocation reason, based on your earlier notes.

Based on this, I guess I have two questions. The first is, is the
revocation reason really required, given that the C# library doesn't appear
to support it, or secondly, am I missing something in the C# implementation
of PgpSignatureSubpacketGenerator.cs

Using pgpdump to inspect the contents of the file which is created, I have
the following :

Old: Signature Packet(tag 2)(305 bytes)
Ver 4 - new
Sig type - Key revocation signature(0x20).
Pub alg - RSA Encrypt or Sign(pub 1)
Hash alg - SHA256(hash 8)
Hashed Sub: signature creation time(sub 2)(4 bytes)
Time - Sat Jun 30 09:48:54 MDT 2012
Sub: issuer key ID(sub 16)(8 bytes)
Key ID - 0x1AEED5494B0BEB3F
Sub: signer's User ID(sub 28)(19 bytes)
User ID - 1940723000211663679
Hash left 2 bytes - 1d eb
RSA m^d mod n(2045 bits) - ...
-> PKCS-1


I also changed the headers as you had originally suggested as follows:

string newHeaderline = "-----BEGIN PGP PUBLIC KEY BLOCK-----";

string oldHeaderLine = "-----BEGIN PGP SIGNATURE-----";

string oldFooterLine = "-----END PGP SIGNATURE-----";

string newFooterLine = "-----END PGP PUBLIC KEY BLOCK-----";


Thanks again for the help.

Jim Treinen.

On Fri, Jun 29, 2012 at 12:59 PM, Atanas Krachev <[email protected]> wrote:

> 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;
>>>>
>>>>
>>>>         }
>>>>
>>>
>>>
>>
>

Reply via email to