diff options
author | David Hook <dgh@bouncycastle.org> | 2021-05-23 19:27:59 +1000 |
---|---|---|
committer | David Hook <dgh@bouncycastle.org> | 2021-05-23 19:27:59 +1000 |
commit | 8ebe171819966753072c65743fd9b1c9e7f090a5 (patch) | |
tree | a5a9a3e907a7b5c096b0d59e17a1481140ba718e | |
parent | github #250 lookup table error (diff) | |
download | BouncyCastle.NET-ed25519-8ebe171819966753072c65743fd9b1c9e7f090a5.tar.xz |
github #23 added method for handling signing subkey
-rw-r--r-- | crypto/src/bcpg/SignaturePacket.cs | 8 | ||||
-rw-r--r-- | crypto/src/openpgp/PgpKeyRingGenerator.cs | 94 | ||||
-rw-r--r-- | crypto/src/openpgp/PgpSignatureGenerator.cs | 6 | ||||
-rw-r--r-- | crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs | 28 | ||||
-rw-r--r-- | crypto/src/openpgp/PgpSignatureSubpacketVector.cs | 22 | ||||
-rw-r--r-- | crypto/test/src/openpgp/test/PgpKeyRingTest.cs | 42 |
6 files changed, 165 insertions, 35 deletions
diff --git a/crypto/src/bcpg/SignaturePacket.cs b/crypto/src/bcpg/SignaturePacket.cs index 5b91c15a3..70138d584 100644 --- a/crypto/src/bcpg/SignaturePacket.cs +++ b/crypto/src/bcpg/SignaturePacket.cs @@ -473,5 +473,11 @@ namespace Org.BouncyCastle.Bcpg } } } - } + public static SignaturePacket FromByteArray(byte[] data) + { + BcpgInputStream input = BcpgInputStream.Wrap(new MemoryStream(data)); + + return new SignaturePacket(input); + } + } } diff --git a/crypto/src/openpgp/PgpKeyRingGenerator.cs b/crypto/src/openpgp/PgpKeyRingGenerator.cs index 4f6a4b12f..352575b0b 100644 --- a/crypto/src/openpgp/PgpKeyRingGenerator.cs +++ b/crypto/src/openpgp/PgpKeyRingGenerator.cs @@ -1,6 +1,5 @@ using System; using System.Collections; - using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; @@ -280,42 +279,70 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp this.AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector, hashAlgorithm); } - /// <summary> - /// Add a subkey with specific hashed and unhashed packets associated with it and - /// default certification. - /// </summary> - /// <param name="keyPair">Public/private key pair.</param> - /// <param name="hashedPackets">Hashed packet values to be included in certification.</param> - /// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param> - /// <exception cref="PgpException"></exception> - public void AddSubKey( + /// <summary> + /// Add a signing subkey to the key ring to be generated with default certification and a primary key binding signature. + /// </summary> + /// <param name="keyPair">The key pair.</param> + /// <param name="hashAlgorithm">The hash algorithm.</param> + /// <param name="primaryKeyBindingHashAlgorithm">The primary-key binding hash algorithm.</param> + public void AddSubKey(PgpKeyPair keyPair, HashAlgorithmTag hashAlgorithm, HashAlgorithmTag primaryKeyBindingHashAlgorithm) + { + this.AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector, hashAlgorithm, primaryKeyBindingHashAlgorithm); + } + + /// <summary> + /// Add a subkey with specific hashed and unhashed packets associated with it and + /// default certification using SHA-1. + /// </summary> + /// <param name="keyPair">Public/private key pair.</param> + /// <param name="hashedPackets">Hashed packet values to be included in certification.</param> + /// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param> + /// <exception cref="PgpException"></exception> + public void AddSubKey( PgpKeyPair keyPair, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets) { - try + AddSubKey(keyPair, hashedPackets, unhashedPackets, HashAlgorithmTag.Sha1); + } + + /// <summary> + /// Add a subkey with specific hashed and unhashed packets associated with it and + /// default certification. + /// </summary> + /// <param name="keyPair">Public/private key pair.</param> + /// <param name="hashedPackets">Hashed packet values to be included in certification.</param> + /// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param> + /// <param name="hashAlgorithm">The hash algorithm.</param> + /// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">exception adding subkey: </exception> + /// <exception cref="PgpException"></exception> + public void AddSubKey( + PgpKeyPair keyPair, + PgpSignatureSubpacketVector hashedPackets, + PgpSignatureSubpacketVector unhashedPackets, + HashAlgorithmTag hashAlgorithm) + { + try { - PgpSignatureGenerator sGen = new PgpSignatureGenerator( - masterKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1); + PgpSignatureGenerator sGen = new PgpSignatureGenerator(masterKey.PublicKey.Algorithm, hashAlgorithm); - // + // // Generate the certification // sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey); - sGen.SetHashedSubpackets(hashedPackets); + sGen.SetHashedSubpackets(hashedPackets); sGen.SetUnhashedSubpackets(unhashedPackets); - IList subSigs = Platform.CreateArrayList(); - - subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey)); + IList subSigs = Platform.CreateArrayList(); + subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey)); - keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, + keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, rawPassPhrase, false, useSha1, rand, false)); - } - catch (PgpException e) + } + catch (PgpException) { - throw e; + throw; } catch (Exception e) { @@ -324,20 +351,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } /// <summary> - /// Add a subkey with specific hashed and unhashed packets associated with it and - /// default certification. + /// Add a signing subkey with specific hashed and unhashed packets associated with it and + /// default certifications, including the primary-key binding signature. /// </summary> /// <param name="keyPair">Public/private key pair.</param> /// <param name="hashedPackets">Hashed packet values to be included in certification.</param> /// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param> /// <param name="hashAlgorithm">The hash algorithm.</param> + /// <param name="primaryKeyBindingHashAlgorithm">The primary-key binding hash algorithm.</param> /// <exception cref="Org.BouncyCastle.Bcpg.OpenPgp.PgpException">exception adding subkey: </exception> /// <exception cref="PgpException"></exception> public void AddSubKey( PgpKeyPair keyPair, PgpSignatureSubpacketVector hashedPackets, PgpSignatureSubpacketVector unhashedPackets, - HashAlgorithmTag hashAlgorithm) + HashAlgorithmTag hashAlgorithm, + HashAlgorithmTag primaryKeyBindingHashAlgorithm) { try { @@ -348,7 +377,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp // sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey); - sGen.SetHashedSubpackets(hashedPackets); + // add primary key binding sub packet + PgpSignatureGenerator pGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, primaryKeyBindingHashAlgorithm); + + pGen.InitSign(PgpSignature.PrimaryKeyBinding, keyPair.PrivateKey); + + PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator(hashedPackets); + + spGen.SetEmbeddedSignature(false, + pGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey)); + + sGen.SetHashedSubpackets(spGen.Generate()); sGen.SetUnhashedSubpackets(unhashedPackets); IList subSigs = Platform.CreateArrayList(); @@ -367,8 +406,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - - /// <summary>Return the secret key ring.</summary> + /// <summary>Return the secret key ring.</summary> public PgpSecretKeyRing GenerateSecretKeyRing() { return new PgpSecretKeyRing(keys); diff --git a/crypto/src/openpgp/PgpSignatureGenerator.cs b/crypto/src/openpgp/PgpSignatureGenerator.cs index c5309689f..74dff2570 100644 --- a/crypto/src/openpgp/PgpSignatureGenerator.cs +++ b/crypto/src/openpgp/PgpSignatureGenerator.cs @@ -75,6 +75,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp lastb = 0; } + public void InitSign( + int sigType, + ISignatureWithDigestFactory signer) + { + } + public void Update( byte b) { diff --git a/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs b/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs index d2177d09c..3987012ae 100644 --- a/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs +++ b/crypto/src/openpgp/PgpSignatureSubpacketGenerator.cs @@ -11,7 +11,33 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { private IList list = Platform.CreateArrayList(); - public void SetRevocable( + + /// <summary> + ///Base constructor, creates an empty generator. + /// </summary> + public PgpSignatureSubpacketGenerator() + { + } + + /// <summary> + /// Constructor for pre-initialising the generator from an existing one. + /// </summary> + /// <param name="sigSubV"> + /// sigSubV an initial set of subpackets. + /// </param> + public PgpSignatureSubpacketGenerator(PgpSignatureSubpacketVector sigSubV) + { + if (sigSubV != null) + { + SignatureSubpacket[] subs = sigSubV.ToSubpacketArray(); + for (int i = 0; i != sigSubV.Count; i++) + { + list.Add(subs[i]); + } + } + } + + public void SetRevocable( bool isCritical, bool isRevocable) { diff --git a/crypto/src/openpgp/PgpSignatureSubpacketVector.cs b/crypto/src/openpgp/PgpSignatureSubpacketVector.cs index 1d3d75941..3dc96ea90 100644 --- a/crypto/src/openpgp/PgpSignatureSubpacketVector.cs +++ b/crypto/src/openpgp/PgpSignatureSubpacketVector.cs @@ -1,6 +1,6 @@ using System; using System.Collections; - +using System.IO; using Org.BouncyCastle.Bcpg.Sig; using Org.BouncyCastle.Utilities; @@ -189,6 +189,26 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp return false; } + public PgpSignatureList GetEmbeddedSignatures() + { + SignatureSubpacket [] sigs = GetSubpackets(SignatureSubpacketTag.EmbeddedSignature); + PgpSignature[] l = new PgpSignature[sigs.Length]; + + for (int i = 0; i < sigs.Length; i++) + { + try + { + l[i] = new PgpSignature(SignaturePacket.FromByteArray(sigs[i].GetData())); + } + catch (IOException e) + { + throw new PgpException("Unable to parse signature packet: " + e.Message, e); + } + } + + return new PgpSignatureList(l); + } + public SignatureSubpacketTag[] GetCriticalTags() { int count = 0; diff --git a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs index 5f1d83459..aed750318 100644 --- a/crypto/test/src/openpgp/test/PgpKeyRingTest.cs +++ b/crypto/test/src/openpgp/test/PgpKeyRingTest.cs @@ -2261,7 +2261,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests } [Test] - public void GenerateSha1Test() + public void GenerateSha256Test() { char[] passPhrase = "hello".ToCharArray(); @@ -2296,11 +2296,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow); PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow); + PgpKeyPair dsaSubKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKpg.GenerateKeyPair(), DateTime.UtcNow); PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, Random); - keyRingGen.AddSubKey(elgKeyPair); + keyRingGen.AddSubKey(elgKeyPair, HashAlgorithmTag.Sha256); + + keyRingGen.AddSubKey(dsaSubKeyPair, HashAlgorithmTag.Sha256, HashAlgorithmTag.Sha256); PgpSecretKeyRing keyRing = keyRingGen.GenerateSecretKeyRing(); @@ -2310,6 +2313,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests PgpPublicKey vKey = null; PgpPublicKey sKey = null; + PgpPublicKey sdKey = null; foreach (PgpPublicKey pk in pubRing.GetPublicKeys()) { @@ -2319,7 +2323,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests } else { - sKey = pk; + if (pk.IsEncryptionKey) + { + sKey = pk; + } + else + { + sdKey = pk; + } } } @@ -2336,6 +2347,29 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests } } } + + foreach (PgpSignature sig in sdKey.GetSignatures()) + { + if (sig.KeyId == vKey.KeyId + && sig.SignatureType == PgpSignature.SubkeyBinding) + { + sig.InitVerify(vKey); + + if (!sig.VerifyCertification(vKey, sdKey)) + { + Fail("failed to verify dsa sub-key signature."); + } + + PgpSignature bindSig = sig.GetHashedSubPackets().GetEmbeddedSignatures()[0]; + + bindSig.InitVerify(sdKey); + + if (!bindSig.VerifyCertification(vKey, sdKey)) + { + Fail("failed to verify dsa sub-key primary binding signature."); + } + } + } } [Test] @@ -2574,7 +2608,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests PerformTest11(); GenerateTest(); - GenerateSha1Test(); + GenerateSha256Test(); RewrapTest(); PublicKeyRingWithX509Test(); SecretKeyRingWithPersonalCertificateTest(); |