diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs
index fa924ff37..672ce9548 100644
--- a/crypto/src/openpgp/PgpPublicKey.cs
+++ b/crypto/src/openpgp/PgpPublicKey.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Drawing;
using System.IO;
using Org.BouncyCastle.Asn1.Cryptlib;
@@ -11,6 +10,7 @@ using Org.BouncyCastle.Asn1.X9;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Math.EC;
using Org.BouncyCastle.Math.EC.Rfc7748;
@@ -115,14 +115,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
else
{
- this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56)
- | ((ulong)fingerprint[fingerprint.Length - 7] << 48)
- | ((ulong)fingerprint[fingerprint.Length - 6] << 40)
- | ((ulong)fingerprint[fingerprint.Length - 5] << 32)
- | ((ulong)fingerprint[fingerprint.Length - 4] << 24)
- | ((ulong)fingerprint[fingerprint.Length - 3] << 16)
- | ((ulong)fingerprint[fingerprint.Length - 2] << 8)
- | (ulong)fingerprint[fingerprint.Length - 1]);
+ this.keyId = (long)Pack.BE_To_UInt64(fingerprint, fingerprint.Length - 8);
if (key is RsaPublicBcpgKey)
{
@@ -490,6 +483,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return (byte[]) fingerprint.Clone();
}
+ public bool HasFingerprint(byte[] fingerprint)
+ {
+ return Arrays.AreEqual(this.fingerprint, fingerprint);
+ }
+
/// <summary>
/// Check if this key has an algorithm type that makes it suitable to use for encryption.
/// </summary>
diff --git a/crypto/src/openpgp/PgpPublicKeyRing.cs b/crypto/src/openpgp/PgpPublicKeyRing.cs
index 46eecd726..f50dd915c 100644
--- a/crypto/src/openpgp/PgpPublicKeyRing.cs
+++ b/crypto/src/openpgp/PgpPublicKeyRing.cs
@@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.IO;
-using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp
@@ -80,6 +79,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return null;
}
+ /// <summary>Return the public key with the passed in fingerprint if it is present.</summary>
+ public virtual PgpPublicKey GetPublicKey(byte[] fingerprint)
+ {
+ foreach (PgpPublicKey k in keys)
+ {
+ if (k.HasFingerprint(fingerprint))
+ return k;
+ }
+
+ return null;
+ }
+
/// <summary>Allows enumeration of all the public keys.</summary>
/// <returns>An <c>IEnumerable</c> of <c>PgpPublicKey</c> objects.</returns>
public virtual IEnumerable<PgpPublicKey> GetPublicKeys()
@@ -239,17 +250,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
public static PgpPublicKeyRing Join(PgpPublicKeyRing first, PgpPublicKeyRing second, bool joinTrustPackets,
bool allowSubkeySigsOnNonSubkey)
{
- if (!Arrays.AreEqual(first.GetPublicKey().GetFingerprint(), second.GetPublicKey().GetFingerprint()))
+ if (!second.GetPublicKey().HasFingerprint(first.GetPublicKey().GetFingerprint()))
throw new ArgumentException("Cannot merge certificates with differing primary keys.");
var secondKeys = new HashSet<long>();
- foreach (var key in second.GetPublicKeys())
+ foreach (var key in second.keys)
{
secondKeys.Add(key.KeyId);
}
var merged = new List<PgpPublicKey>();
- foreach (var key in first.GetPublicKeys())
+ foreach (var key in first.keys)
{
var copy = second.GetPublicKey(key.KeyId);
if (copy != null)
diff --git a/crypto/src/openpgp/PgpPublicKeyRingBundle.cs b/crypto/src/openpgp/PgpPublicKeyRingBundle.cs
index 473d0ae5b..1940c979e 100644
--- a/crypto/src/openpgp/PgpPublicKeyRingBundle.cs
+++ b/crypto/src/openpgp/PgpPublicKeyRingBundle.cs
@@ -8,10 +8,10 @@ using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp
{
- /// <remarks>
- /// Often a PGP key ring file is made up of a succession of master/sub-key key rings.
- /// If you want to read an entire public key file in one hit this is the class for you.
- /// </remarks>
+ /// <remarks>
+ /// Often a PGP key ring file is made up of a succession of master/sub-key key rings.
+ /// If you want to read an entire public key file in one hit this is the class for you.
+ /// </remarks>
public class PgpPublicKeyRingBundle
{
private readonly IDictionary<long, PgpPublicKeyRing> m_pubRings;
@@ -66,7 +66,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
/// <summary>Allow enumeration of the public key rings making up this collection.</summary>
public IEnumerable<PgpPublicKeyRing> GetKeyRings()
{
- return CollectionUtilities.Proxy(m_pubRings.Values);
+ return CollectionUtilities.Proxy(KeyRings);
}
/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
@@ -96,7 +96,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
var compareInfo = CultureInfo.InvariantCulture.CompareInfo;
var compareOptions = ignoreCase ? CompareOptions.OrdinalIgnoreCase : CompareOptions.Ordinal;
- foreach (PgpPublicKeyRing pubRing in GetKeyRings())
+ foreach (PgpPublicKeyRing pubRing in KeyRings)
{
foreach (string nextUserID in pubRing.GetPublicKey().GetUserIds())
{
@@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
/// <param name="keyId">The ID of the public key to return.</param>
public PgpPublicKey GetPublicKey(long keyId)
{
- foreach (PgpPublicKeyRing pubRing in GetKeyRings())
+ foreach (PgpPublicKeyRing pubRing in KeyRings)
{
PgpPublicKey pub = pubRing.GetPublicKey(keyId);
if (pub != null)
@@ -135,7 +135,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
if (m_pubRings.TryGetValue(keyId, out var keyRing))
return keyRing;
- foreach (PgpPublicKeyRing pubRing in GetKeyRings())
+ foreach (PgpPublicKeyRing pubRing in KeyRings)
{
if (pubRing.GetPublicKey(keyId) != null)
return pubRing;
@@ -144,11 +144,39 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return null;
}
- /// <summary>
- /// Return true if a key matching the passed in key ID is present, false otherwise.
- /// </summary>
- /// <param name="keyID">key ID to look for.</param>
- public bool Contains(long keyID)
+ /// <summary>Return the PGP public key associated with the given key fingerprint.</summary>
+ /// <param name="fingerprint">the public key fingerprint to match against.</param>
+ public PgpPublicKey GetPublicKey(byte[] fingerprint)
+ {
+ foreach (PgpPublicKeyRing pubRing in KeyRings)
+ {
+ PgpPublicKey pub = pubRing.GetPublicKey(fingerprint);
+ if (pub != null)
+ return pub;
+ }
+
+ return null;
+ }
+
+ /// <summary>Return the public key ring which contains the key associated with the given key fingerprint.
+ /// </summary>
+ /// <param name="fingerprint">the public key fingerprint to match against.</param>
+ public PgpPublicKeyRing GetPublicKeyRing(byte[] fingerprint)
+ {
+ foreach (PgpPublicKeyRing pubRing in KeyRings)
+ {
+ if (pubRing.GetPublicKey(fingerprint) != null)
+ return pubRing;
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Return true if a key matching the passed in key ID is present, false otherwise.
+ /// </summary>
+ /// <param name="keyID">key ID to look for.</param>
+ public bool Contains(long keyID)
{
return GetPublicKey(keyID) != null;
}
@@ -170,14 +198,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
- /// <summary>
- /// Return a new bundle containing the contents of the passed in bundle and
- /// the passed in public key ring.
- /// </summary>
- /// <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be added to.</param>
- /// <param name="publicKeyRing">The key ring to be added.</param>
- /// <returns>A new <c>PgpPublicKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
- /// <exception cref="ArgumentException">If the keyId for the passed in key ring is already present.</exception>
+ private ICollection<PgpPublicKeyRing> KeyRings => m_pubRings.Values;
+
+ /// <summary>
+ /// Return a new bundle containing the contents of the passed in bundle and
+ /// the passed in public key ring.
+ /// </summary>
+ /// <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be added to.</param>
+ /// <param name="publicKeyRing">The key ring to be added.</param>
+ /// <returns>A new <c>PgpPublicKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
+ /// <exception cref="ArgumentException">If the keyId for the passed in key ring is already present.</exception>
public static PgpPublicKeyRingBundle AddPublicKeyRing(PgpPublicKeyRingBundle bundle,
PgpPublicKeyRing publicKeyRing)
{
diff --git a/crypto/src/openpgp/PgpSecretKeyRing.cs b/crypto/src/openpgp/PgpSecretKeyRing.cs
index a070aa132..ff644545f 100644
--- a/crypto/src/openpgp/PgpSecretKeyRing.cs
+++ b/crypto/src/openpgp/PgpSecretKeyRing.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using Org.BouncyCastle.Security;
-using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp
@@ -115,6 +114,38 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return keys[0].PublicKey;
}
+ /// <summary>Return the public key referred to by the passed in keyID if it is present.</summary>
+ public PgpPublicKey GetPublicKey(long keyID)
+ {
+ PgpSecretKey key = GetSecretKey(keyID);
+ if (key != null)
+ return key.PublicKey;
+
+ foreach (PgpPublicKey k in extraPubKeys)
+ {
+ if (keyID == k.KeyId)
+ return k;
+ }
+
+ return null;
+ }
+
+ /// <summary>Return the public key with the passed in fingerprint if it is present.</summary>
+ public PgpPublicKey GetPublicKey(byte[] fingerprint)
+ {
+ PgpSecretKey key = GetSecretKey(fingerprint);
+ if (key != null)
+ return key.PublicKey;
+
+ foreach (PgpPublicKey k in extraPubKeys)
+ {
+ if (k.HasFingerprint(fingerprint))
+ return k;
+ }
+
+ return null;
+ }
+
/**
* Return any keys carrying a signature issued by the key represented by keyID.
*
@@ -165,6 +196,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return CollectionUtilities.Proxy(keys);
}
+ /// <summary>Return the secret key referred to by the passed in keyID if it is present.</summary>
public PgpSecretKey GetSecretKey(long keyId)
{
foreach (PgpSecretKey k in keys)
@@ -176,6 +208,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
return null;
}
+ /// <summary>Return the secret key associated with the passed in fingerprint if it is present.</summary>
+ public PgpSecretKey GetSecretKey(byte[] fingerprint)
+ {
+ foreach (PgpSecretKey k in keys)
+ {
+ if (k.PublicKey.HasFingerprint(fingerprint))
+ return k;
+ }
+
+ return null;
+ }
+
/// <summary>
/// Return an iterator of the public keys in the secret key ring that
/// have no matching private key. At the moment only personal certificate data
@@ -247,7 +291,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
{
var newKeys = new List<PgpSecretKey>(ring.keys.Count);
- foreach (PgpSecretKey secretKey in ring.GetSecretKeys())
+ foreach (PgpSecretKey secretKey in ring.keys)
{
if (secretKey.IsPrivateKeyEmpty)
{
diff --git a/crypto/src/openpgp/PgpSecretKeyRingBundle.cs b/crypto/src/openpgp/PgpSecretKeyRingBundle.cs
index 695c882b7..fe9a2461a 100644
--- a/crypto/src/openpgp/PgpSecretKeyRingBundle.cs
+++ b/crypto/src/openpgp/PgpSecretKeyRingBundle.cs
@@ -8,10 +8,10 @@ using Org.BouncyCastle.Utilities.Collections;
namespace Org.BouncyCastle.Bcpg.OpenPgp
{
- /// <remarks>
- /// Often a PGP key ring file is made up of a succession of master/sub-key key rings.
- /// If you want to read an entire secret key file in one hit this is the class for you.
- /// </remarks>
+ /// <remarks>
+ /// Often a PGP key ring file is made up of a succession of master/sub-key key rings.
+ /// If you want to read an entire secret key file in one hit this is the class for you.
+ /// </remarks>
public class PgpSecretKeyRingBundle
{
private readonly IDictionary<long, PgpSecretKeyRing> m_secretRings;
@@ -66,7 +66,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
/// <summary>Allow enumeration of the secret key rings making up this collection.</summary>
public IEnumerable<PgpSecretKeyRing> GetKeyRings()
{
- return CollectionUtilities.Proxy(m_secretRings.Values);
+ return CollectionUtilities.Proxy(KeyRings);
}
/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
@@ -96,7 +96,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
var compareInfo = CultureInfo.InvariantCulture.CompareInfo;
var compareOptions = ignoreCase ? CompareOptions.OrdinalIgnoreCase : CompareOptions.Ordinal;
- foreach (PgpSecretKeyRing secRing in GetKeyRings())
+ foreach (PgpSecretKeyRing secRing in KeyRings)
{
foreach (string nextUserID in secRing.GetSecretKey().UserIds)
{
@@ -118,7 +118,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
/// <param name="keyId">The ID of the secret key to return.</param>
public PgpSecretKey GetSecretKey(long keyId)
{
- foreach (PgpSecretKeyRing secRing in GetKeyRings())
+ foreach (PgpSecretKeyRing secRing in KeyRings)
{
PgpSecretKey sec = secRing.GetSecretKey(keyId);
if (sec != null)
@@ -135,7 +135,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
if (m_secretRings.TryGetValue(keyId, out var keyRing))
return keyRing;
- foreach (PgpSecretKeyRing secretRing in GetKeyRings())
+ foreach (PgpSecretKeyRing secretRing in KeyRings)
{
if (secretRing.GetSecretKey(keyId) != null)
return secretRing;
@@ -170,14 +170,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
}
}
- /// <summary>
- /// Return a new bundle containing the contents of the passed in bundle and
- /// the passed in secret key ring.
- /// </summary>
- /// <param name="bundle">The <c>PgpSecretKeyRingBundle</c> the key ring is to be added to.</param>
- /// <param name="secretKeyRing">The key ring to be added.</param>
- /// <returns>A new <c>PgpSecretKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
- /// <exception cref="ArgumentException">If the keyId for the passed in key ring is already present.</exception>
+ private ICollection<PgpSecretKeyRing> KeyRings => m_secretRings.Values;
+
+ /// <summary>
+ /// Return a new bundle containing the contents of the passed in bundle and
+ /// the passed in secret key ring.
+ /// </summary>
+ /// <param name="bundle">The <c>PgpSecretKeyRingBundle</c> the key ring is to be added to.</param>
+ /// <param name="secretKeyRing">The key ring to be added.</param>
+ /// <returns>A new <c>PgpSecretKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
+ /// <exception cref="ArgumentException">If the keyId for the passed in key ring is already present.</exception>
public static PgpSecretKeyRingBundle AddSecretKeyRing(PgpSecretKeyRingBundle bundle,
PgpSecretKeyRing secretKeyRing)
{
diff --git a/crypto/test/src/openpgp/test/PGPRSATest.cs b/crypto/test/src/openpgp/test/PGPRSATest.cs
index 6de95fbeb..56d761c16 100644
--- a/crypto/test/src/openpgp/test/PGPRSATest.cs
+++ b/crypto/test/src/openpgp/test/PGPRSATest.cs
@@ -325,7 +325,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
PgpPublicKey pubKey = pgpPub.GetPublicKey();
- if (!Arrays.AreEqual(pubKey.GetFingerprint(), Hex.Decode("4FFB9F0884266C715D1CEAC804A3BBFA")))
+ byte[] expectedVersion3 = Hex.Decode("4FFB9F0884266C715D1CEAC804A3BBFA");
+ if (!Arrays.AreEqual(pubKey.GetFingerprint(), expectedVersion3))
+ {
+ Fail("version 3 fingerprint test failed");
+ }
+ if (!pubKey.HasFingerprint(expectedVersion3))
{
Fail("version 3 fingerprint test failed");
}
@@ -337,10 +342,15 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
pubKey = pgpPub.GetPublicKey();
- if (!Arrays.AreEqual(pubKey.GetFingerprint(), Hex.Decode("3062363c1046a01a751946bb35586146fdf3f373")))
+ byte[] expectedVersion4 = Hex.Decode("3062363c1046a01a751946bb35586146fdf3f373");
+ if (!Arrays.AreEqual(pubKey.GetFingerprint(), expectedVersion4))
{
Fail("version 4 fingerprint test failed");
}
+ if (!pubKey.HasFingerprint(expectedVersion4))
+ {
+ Fail("version 4 fingerprint test failed");
+ }
}
private void MixedTest(
diff --git a/crypto/test/src/openpgp/test/PgpEdDsaTest.cs b/crypto/test/src/openpgp/test/PgpEdDsaTest.cs
index f67d19a7f..c3cdd53f0 100644
--- a/crypto/test/src/openpgp/test/PgpEdDsaTest.cs
+++ b/crypto/test/src/openpgp/test/PgpEdDsaTest.cs
@@ -202,8 +202,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
PgpPublicKeyRing pubKeyRing = new PgpPublicKeyRing(aIn);
- IsTrue(AreEqual(Hex.Decode("EB85 BB5F A33A 75E1 5E94 4E63 F231 550C 4F47 E38E"),
- pubKeyRing.GetPublicKey().GetFingerprint()));
+ IsTrue(AreEqual(pubKeyRing.GetPublicKey().GetFingerprint(),
+ Hex.Decode("EB85 BB5F A33A 75E1 5E94 4E63 F231 550C 4F47 E38E")));
+ IsTrue(pubKeyRing.GetPublicKey().HasFingerprint(
+ Hex.Decode("EB85 BB5F A33A 75E1 5E94 4E63 F231 550C 4F47 E38E")));
aIn = new ArmoredInputStream(new MemoryStream(Strings.ToByteArray(edDSASecretKey), false));
|