Skip to content

Commit 8ebe171

Browse files
committed
github #23 added method for handling signing subkey
1 parent 6e06829 commit 8ebe171

File tree

6 files changed

+165
-35
lines changed

6 files changed

+165
-35
lines changed

crypto/src/bcpg/SignaturePacket.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,5 +473,11 @@ private void setCreationTime()
473473
}
474474
}
475475
}
476-
}
476+
public static SignaturePacket FromByteArray(byte[] data)
477+
{
478+
BcpgInputStream input = BcpgInputStream.Wrap(new MemoryStream(data));
479+
480+
return new SignaturePacket(input);
481+
}
482+
}
477483
}

crypto/src/openpgp/PgpKeyRingGenerator.cs

Lines changed: 66 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using System;
22
using System.Collections;
3-
43
using Org.BouncyCastle.Security;
54
using Org.BouncyCastle.Utilities;
65

@@ -280,42 +279,70 @@ public void AddSubKey(PgpKeyPair keyPair, HashAlgorithmTag hashAlgorithm)
280279
this.AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector, hashAlgorithm);
281280
}
282281

283-
/// <summary>
284-
/// Add a subkey with specific hashed and unhashed packets associated with it and
285-
/// default certification.
286-
/// </summary>
287-
/// <param name="keyPair">Public/private key pair.</param>
288-
/// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
289-
/// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
290-
/// <exception cref="PgpException"></exception>
291-
public void AddSubKey(
282+
/// <summary>
283+
/// Add a signing subkey to the key ring to be generated with default certification and a primary key binding signature.
284+
/// </summary>
285+
/// <param name="keyPair">The key pair.</param>
286+
/// <param name="hashAlgorithm">The hash algorithm.</param>
287+
/// <param name="primaryKeyBindingHashAlgorithm">The primary-key binding hash algorithm.</param>
288+
public void AddSubKey(PgpKeyPair keyPair, HashAlgorithmTag hashAlgorithm, HashAlgorithmTag primaryKeyBindingHashAlgorithm)
289+
{
290+
this.AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector, hashAlgorithm, primaryKeyBindingHashAlgorithm);
291+
}
292+
293+
/// <summary>
294+
/// Add a subkey with specific hashed and unhashed packets associated with it and
295+
/// default certification using SHA-1.
296+
/// </summary>
297+
/// <param name="keyPair">Public/private key pair.</param>
298+
/// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
299+
/// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
300+
/// <exception cref="PgpException"></exception>
301+
public void AddSubKey(
292302
PgpKeyPair keyPair,
293303
PgpSignatureSubpacketVector hashedPackets,
294304
PgpSignatureSubpacketVector unhashedPackets)
295305
{
296-
try
306+
AddSubKey(keyPair, hashedPackets, unhashedPackets, HashAlgorithmTag.Sha1);
307+
}
308+
309+
/// <summary>
310+
/// Add a subkey with specific hashed and unhashed packets associated with it and
311+
/// default certification.
312+
/// </summary>
313+
/// <param name="keyPair">Public/private key pair.</param>
314+
/// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
315+
/// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
316+
/// <param name="hashAlgorithm">The hash algorithm.</param>
317+
/// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">exception adding subkey: </exception>
318+
/// <exception cref="PgpException"></exception>
319+
public void AddSubKey(
320+
PgpKeyPair keyPair,
321+
PgpSignatureSubpacketVector hashedPackets,
322+
PgpSignatureSubpacketVector unhashedPackets,
323+
HashAlgorithmTag hashAlgorithm)
324+
{
325+
try
297326
{
298-
PgpSignatureGenerator sGen = new PgpSignatureGenerator(
299-
masterKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
327+
PgpSignatureGenerator sGen = new PgpSignatureGenerator(masterKey.PublicKey.Algorithm, hashAlgorithm);
300328

301-
//
329+
//
302330
// Generate the certification
303331
//
304332
sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey);
305333

306-
sGen.SetHashedSubpackets(hashedPackets);
334+
sGen.SetHashedSubpackets(hashedPackets);
307335
sGen.SetUnhashedSubpackets(unhashedPackets);
308336

309-
IList subSigs = Platform.CreateArrayList();
310-
311-
subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
337+
IList subSigs = Platform.CreateArrayList();
338+
subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
312339

313-
keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm,
340+
keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm,
314341
rawPassPhrase, false, useSha1, rand, false));
315-
}
316-
catch (PgpException e)
342+
}
343+
catch (PgpException)
317344
{
318-
throw e;
345+
throw;
319346
}
320347
catch (Exception e)
321348
{
@@ -324,20 +351,22 @@ public void AddSubKey(
324351
}
325352

326353
/// <summary>
327-
/// Add a subkey with specific hashed and unhashed packets associated with it and
328-
/// default certification.
354+
/// Add a signing subkey with specific hashed and unhashed packets associated with it and
355+
/// default certifications, including the primary-key binding signature.
329356
/// </summary>
330357
/// <param name="keyPair">Public/private key pair.</param>
331358
/// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
332359
/// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
333360
/// <param name="hashAlgorithm">The hash algorithm.</param>
361+
/// <param name="primaryKeyBindingHashAlgorithm">The primary-key binding hash algorithm.</param>
334362
/// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">exception adding subkey: </exception>
335363
/// <exception cref="PgpException"></exception>
336364
public void AddSubKey(
337365
PgpKeyPair keyPair,
338366
PgpSignatureSubpacketVector hashedPackets,
339367
PgpSignatureSubpacketVector unhashedPackets,
340-
HashAlgorithmTag hashAlgorithm)
368+
HashAlgorithmTag hashAlgorithm,
369+
HashAlgorithmTag primaryKeyBindingHashAlgorithm)
341370
{
342371
try
343372
{
@@ -348,7 +377,17 @@ public void AddSubKey(
348377
//
349378
sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey);
350379

351-
sGen.SetHashedSubpackets(hashedPackets);
380+
// add primary key binding sub packet
381+
PgpSignatureGenerator pGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, primaryKeyBindingHashAlgorithm);
382+
383+
pGen.InitSign(PgpSignature.PrimaryKeyBinding, keyPair.PrivateKey);
384+
385+
PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(hashedPackets);
386+
387+
spGen.SetEmbeddedSignature(false,
388+
pGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
389+
390+
sGen.SetHashedSubpackets(spGen.Generate());
352391
sGen.SetUnhashedSubpackets(unhashedPackets);
353392

354393
IList subSigs = Platform.CreateArrayList();
@@ -367,8 +406,7 @@ public void AddSubKey(
367406
}
368407
}
369408

370-
371-
/// <summary>Return the secret key ring.</summary>
409+
/// <summary>Return the secret key ring.</summary>
372410
public PgpSecretKeyRing GenerateSecretKeyRing()
373411
{
374412
return new PgpSecretKeyRing(keys);

crypto/src/openpgp/PgpSignatureGenerator.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ public void InitSign(
7575
lastb = 0;
7676
}
7777

78+
public void InitSign(
79+
int sigType,
80+
ISignatureWithDigestFactory signer)
81+
{
82+
}
83+
7884
public void Update(
7985
byte b)
8086
{

crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,33 @@ public class PgpSignatureSubpacketGenerator
1111
{
1212
private IList list = Platform.CreateArrayList();
1313

14-
public void SetRevocable(
14+
15+
/// <summary>
16+
///Base constructor, creates an empty generator.
17+
/// </summary>
18+
public PgpSignatureSubpacketGenerator()
19+
{
20+
}
21+
22+
/// <summary>
23+
/// Constructor for pre-initialising the generator from an existing one.
24+
/// </summary>
25+
/// <param name="sigSubV">
26+
/// sigSubV an initial set of subpackets.
27+
/// </param>
28+
public PgpSignatureSubpacketGenerator(PgpSignatureSubpacketVector sigSubV)
29+
{
30+
if (sigSubV != null)
31+
{
32+
SignatureSubpacket[] subs = sigSubV.ToSubpacketArray();
33+
for (int i = 0; i != sigSubV.Count; i++)
34+
{
35+
list.Add(subs[i]);
36+
}
37+
}
38+
}
39+
40+
public void SetRevocable(
1541
bool isCritical,
1642
bool isRevocable)
1743
{

crypto/src/openpgp/PgpSignatureSubpacketVector.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using System;
22
using System.Collections;
3-
3+
using System.IO;
44
using Org.BouncyCastle.Bcpg.Sig;
55
using Org.BouncyCastle.Utilities;
66

@@ -189,6 +189,26 @@ public bool IsPrimaryUserId()
189189
return false;
190190
}
191191

192+
public PgpSignatureList GetEmbeddedSignatures()
193+
{
194+
SignatureSubpacket [] sigs = GetSubpackets(SignatureSubpacketTag.EmbeddedSignature);
195+
PgpSignature[] l = new PgpSignature[sigs.Length];
196+
197+
for (int i = 0; i < sigs.Length; i++)
198+
{
199+
try
200+
{
201+
l[i] = new PgpSignature(SignaturePacket.FromByteArray(sigs[i].GetData()));
202+
}
203+
catch (IOException e)
204+
{
205+
throw new PgpException("Unable to parse signature packet: " + e.Message, e);
206+
}
207+
}
208+
209+
return new PgpSignatureList(l);
210+
}
211+
192212
public SignatureSubpacketTag[] GetCriticalTags()
193213
{
194214
int count = 0;

crypto/test/src/openpgp/test/PgpKeyRingTest.cs

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2261,7 +2261,7 @@ public void InsertMasterTest()
22612261
}
22622262

22632263
[Test]
2264-
public void GenerateSha1Test()
2264+
public void GenerateSha256Test()
22652265
{
22662266
char[] passPhrase = "hello".ToCharArray();
22672267

@@ -2296,11 +2296,14 @@ public void GenerateSha1Test()
22962296

22972297
PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow);
22982298
PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow);
2299+
PgpKeyPair dsaSubKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKpg.GenerateKeyPair(), DateTime.UtcNow);
22992300

23002301
PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair,
23012302
"test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, Random);
23022303

2303-
keyRingGen.AddSubKey(elgKeyPair);
2304+
keyRingGen.AddSubKey(elgKeyPair, HashAlgorithmTag.Sha256);
2305+
2306+
keyRingGen.AddSubKey(dsaSubKeyPair, HashAlgorithmTag.Sha256, HashAlgorithmTag.Sha256);
23042307

23052308
PgpSecretKeyRing keyRing = keyRingGen.GenerateSecretKeyRing();
23062309

@@ -2310,6 +2313,7 @@ public void GenerateSha1Test()
23102313

23112314
PgpPublicKey vKey = null;
23122315
PgpPublicKey sKey = null;
2316+
PgpPublicKey sdKey = null;
23132317

23142318
foreach (PgpPublicKey pk in pubRing.GetPublicKeys())
23152319
{
@@ -2319,7 +2323,14 @@ public void GenerateSha1Test()
23192323
}
23202324
else
23212325
{
2322-
sKey = pk;
2326+
if (pk.IsEncryptionKey)
2327+
{
2328+
sKey = pk;
2329+
}
2330+
else
2331+
{
2332+
sdKey = pk;
2333+
}
23232334
}
23242335
}
23252336

@@ -2336,6 +2347,29 @@ public void GenerateSha1Test()
23362347
}
23372348
}
23382349
}
2350+
2351+
foreach (PgpSignature sig in sdKey.GetSignatures())
2352+
{
2353+
if (sig.KeyId == vKey.KeyId
2354+
&& sig.SignatureType == PgpSignature.SubkeyBinding)
2355+
{
2356+
sig.InitVerify(vKey);
2357+
2358+
if (!sig.VerifyCertification(vKey, sdKey))
2359+
{
2360+
Fail("failed to verify dsa sub-key signature.");
2361+
}
2362+
2363+
PgpSignature bindSig = sig.GetHashedSubPackets().GetEmbeddedSignatures()[0];
2364+
2365+
bindSig.InitVerify(sdKey);
2366+
2367+
if (!bindSig.VerifyCertification(vKey, sdKey))
2368+
{
2369+
Fail("failed to verify dsa sub-key primary binding signature.");
2370+
}
2371+
}
2372+
}
23392373
}
23402374

23412375
[Test]
@@ -2574,7 +2608,7 @@ public override void PerformTest()
25742608
PerformTest11();
25752609

25762610
GenerateTest();
2577-
GenerateSha1Test();
2611+
GenerateSha256Test();
25782612
RewrapTest();
25792613
PublicKeyRingWithX509Test();
25802614
SecretKeyRingWithPersonalCertificateTest();

0 commit comments

Comments
 (0)