summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpPublicKey.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/openpgp/PgpPublicKey.cs')
-rw-r--r--crypto/src/openpgp/PgpPublicKey.cs967
1 files changed, 523 insertions, 444 deletions
diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs

index b0720146c..904e29913 100644 --- a/crypto/src/openpgp/PgpPublicKey.cs +++ b/crypto/src/openpgp/PgpPublicKey.cs
@@ -2,88 +2,107 @@ using System; using System.Collections; using System.IO; +using Org.BouncyCastle.Asn1.Sec; +using Org.BouncyCastle.Asn1.X9; using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.IO; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Math.EC; using Org.BouncyCastle.Security; using Org.BouncyCastle.Utilities; using Org.BouncyCastle.Utilities.Collections; namespace Org.BouncyCastle.Bcpg.OpenPgp { - /// <remarks>General class to handle a PGP public key object.</remarks> + /// <remarks>General class to handle a PGP public key object.</remarks> public class PgpPublicKey { - private static readonly int[] MasterKeyCertificationTypes = new int[] - { - PgpSignature.PositiveCertification, - PgpSignature.CasualCertification, - PgpSignature.NoCertification, - PgpSignature.DefaultCertification - }; - - private long keyId; - private byte[] fingerprint; - private int keyStrength; - - internal PublicKeyPacket publicPk; - internal TrustPacket trustPk; - internal IList keySigs = Platform.CreateArrayList(); - internal IList ids = Platform.CreateArrayList(); - internal IList idTrusts = Platform.CreateArrayList(); - internal IList idSigs = Platform.CreateArrayList(); - internal IList subSigs; - - private void Init() + public static byte[] CalculateFingerprint(PublicKeyPacket publicPk) { IBcpgKey key = publicPk.Key; + IDigest digest; - if (publicPk.Version <= 3) + if (publicPk.Version <= 3) { - RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key; + RsaPublicBcpgKey rK = (RsaPublicBcpgKey)key; - this.keyId = rK.Modulus.LongValue; - - try + try { - IDigest digest = DigestUtilities.GetDigest("MD5"); - - byte[] bytes = rK.Modulus.ToByteArrayUnsigned(); - digest.BlockUpdate(bytes, 0, bytes.Length); - - bytes = rK.PublicExponent.ToByteArrayUnsigned(); - digest.BlockUpdate(bytes, 0, bytes.Length); - - this.fingerprint = DigestUtilities.DoFinal(digest); + digest = DigestUtilities.GetDigest("MD5"); + UpdateDigest(digest, rK.Modulus); + UpdateDigest(digest, rK.PublicExponent); } - //catch (NoSuchAlgorithmException) - catch (Exception e) + catch (Exception e) { - throw new IOException("can't find MD5", e); + throw new PgpException("can't encode key components: " + e.Message, e); } - - this.keyStrength = rK.Modulus.BitLength; } else { - byte[] kBytes = publicPk.GetEncodedContents(); - - try + try { - IDigest digest = DigestUtilities.GetDigest("SHA1"); + byte[] kBytes = publicPk.GetEncodedContents(); - digest.Update(0x99); + digest = DigestUtilities.GetDigest("SHA1"); + + digest.Update(0x99); digest.Update((byte)(kBytes.Length >> 8)); digest.Update((byte)kBytes.Length); digest.BlockUpdate(kBytes, 0, kBytes.Length); - this.fingerprint = DigestUtilities.DoFinal(digest); } catch (Exception e) { - throw new IOException("can't find SHA1", e); + throw new PgpException("can't encode key components: " + e.Message, e); } + } + + return DigestUtilities.DoFinal(digest); + } + + private static void UpdateDigest(IDigest d, BigInteger b) + { + byte[] bytes = b.ToByteArrayUnsigned(); + d.BlockUpdate(bytes, 0, bytes.Length); + } + + private static readonly int[] MasterKeyCertificationTypes = new int[] + { + PgpSignature.PositiveCertification, + PgpSignature.CasualCertification, + PgpSignature.NoCertification, + PgpSignature.DefaultCertification + }; - this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56) + private long keyId; + private byte[] fingerprint; + private int keyStrength; + + internal PublicKeyPacket publicPk; + internal TrustPacket trustPk; + internal IList keySigs = Platform.CreateArrayList(); + internal IList ids = Platform.CreateArrayList(); + internal IList idTrusts = Platform.CreateArrayList(); + internal IList idSigs = Platform.CreateArrayList(); + internal IList subSigs; + + private void Init() + { + IBcpgKey key = publicPk.Key; + + this.fingerprint = CalculateFingerprint(publicPk); + + if (publicPk.Version <= 3) + { + RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key; + + this.keyId = rK.Modulus.LongValue; + this.keyStrength = rK.Modulus.BitLength; + } + 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) @@ -92,7 +111,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp | ((ulong)fingerprint[fingerprint.Length - 2] << 8) | (ulong)fingerprint[fingerprint.Length - 1]); - if (key is RsaPublicBcpgKey) + if (key is RsaPublicBcpgKey) { this.keyStrength = ((RsaPublicBcpgKey)key).Modulus.BitLength; } @@ -104,60 +123,81 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { this.keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength; } + else if (key is ECPublicBcpgKey) + { + this.keyStrength = ECKeyPairGenerator.FindECCurveByOid(((ECPublicBcpgKey)key).CurveOid).Curve.FieldSize; + } } } - /// <summary> - /// Create a PgpPublicKey from the passed in lightweight one. - /// </summary> - /// <remarks> - /// Note: the time passed in affects the value of the key's keyId, so you probably only want - /// to do this once for a lightweight key, or make sure you keep track of the time you used. - /// </remarks> - /// <param name="algorithm">Asymmetric algorithm type representing the public key.</param> - /// <param name="pubKey">Actual public key to associate.</param> - /// <param name="time">Date of creation.</param> - /// <exception cref="ArgumentException">If <c>pubKey</c> is not public.</exception> - /// <exception cref="PgpException">On key creation problem.</exception> + /// <summary> + /// Create a PgpPublicKey from the passed in lightweight one. + /// </summary> + /// <remarks> + /// Note: the time passed in affects the value of the key's keyId, so you probably only want + /// to do this once for a lightweight key, or make sure you keep track of the time you used. + /// </remarks> + /// <param name="algorithm">Asymmetric algorithm type representing the public key.</param> + /// <param name="pubKey">Actual public key to associate.</param> + /// <param name="time">Date of creation.</param> + /// <exception cref="ArgumentException">If <c>pubKey</c> is not public.</exception> + /// <exception cref="PgpException">On key creation problem.</exception> public PgpPublicKey( PublicKeyAlgorithmTag algorithm, AsymmetricKeyParameter pubKey, DateTime time) { - if (pubKey.IsPrivate) - throw new ArgumentException("Expected a public key", "pubKey"); + if (pubKey.IsPrivate) + throw new ArgumentException("Expected a public key", "pubKey"); - IBcpgKey bcpgKey; + IBcpgKey bcpgKey; if (pubKey is RsaKeyParameters) { RsaKeyParameters rK = (RsaKeyParameters) pubKey; - bcpgKey = new RsaPublicBcpgKey(rK.Modulus, rK.Exponent); + bcpgKey = new RsaPublicBcpgKey(rK.Modulus, rK.Exponent); } else if (pubKey is DsaPublicKeyParameters) { DsaPublicKeyParameters dK = (DsaPublicKeyParameters) pubKey; DsaParameters dP = dK.Parameters; - bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y); + bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y); + } + else if (pubKey is ECPublicKeyParameters) + { + ECPublicKeyParameters ecK = (ECPublicKeyParameters)pubKey; + + if (algorithm == PublicKeyAlgorithmTag.ECDH) + { + bcpgKey = new ECDHPublicBcpgKey(ecK.PublicKeyParamSet, ecK.Q, HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag.Aes128); + } + else if (algorithm == PublicKeyAlgorithmTag.ECDsa) + { + bcpgKey = new ECDsaPublicBcpgKey(ecK.PublicKeyParamSet, ecK.Q); + } + else + { + throw new PgpException("unknown EC algorithm"); + } } else if (pubKey is ElGamalPublicKeyParameters) { ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey; ElGamalParameters eS = eK.Parameters; - bcpgKey = new ElGamalPublicBcpgKey(eS.P, eS.G, eK.Y); + bcpgKey = new ElGamalPublicBcpgKey(eS.P, eS.G, eK.Y); } else { throw new PgpException("unknown key class"); } - this.publicPk = new PublicKeyPacket(algorithm, time, bcpgKey); + this.publicPk = new PublicKeyPacket(algorithm, time, bcpgKey); this.ids = Platform.CreateArrayList(); this.idSigs = Platform.CreateArrayList(); - try + try { Init(); } @@ -167,7 +207,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - /// <summary>Constructor for a sub-key.</summary> + public PgpPublicKey(PublicKeyPacket publicPk) + : this(publicPk, Platform.CreateArrayList(), Platform.CreateArrayList()) + { + } + + /// <summary>Constructor for a sub-key.</summary> internal PgpPublicKey( PublicKeyPacket publicPk, TrustPacket trustPk, @@ -177,10 +222,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp this.trustPk = trustPk; this.subSigs = sigs; - Init(); + Init(); } - internal PgpPublicKey( + internal PgpPublicKey( PgpPublicKey key, TrustPacket trust, IList subSigs) @@ -189,19 +234,19 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp this.trustPk = trust; this.subSigs = subSigs; - this.fingerprint = key.fingerprint; + this.fingerprint = key.fingerprint; this.keyId = key.keyId; this.keyStrength = key.keyStrength; } - /// <summary>Copy constructor.</summary> - /// <param name="pubKey">The public key to copy.</param> + /// <summary>Copy constructor.</summary> + /// <param name="pubKey">The public key to copy.</param> internal PgpPublicKey( PgpPublicKey pubKey) { this.publicPk = pubKey.publicPk; - this.keySigs = Platform.CreateArrayList(pubKey.keySigs); + this.keySigs = Platform.CreateArrayList(pubKey.keySigs); this.ids = Platform.CreateArrayList(pubKey.ids); this.idTrusts = Platform.CreateArrayList(pubKey.idTrusts); this.idSigs = Platform.CreateArrayList(pubKey.idSigs.Count); @@ -210,7 +255,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp this.idSigs.Add(Platform.CreateArrayList((IList)pubKey.idSigs[i])); } - if (pubKey.subSigs != null) + if (pubKey.subSigs != null) { this.subSigs = Platform.CreateArrayList(pubKey.subSigs.Count); for (int i = 0; i != pubKey.subSigs.Count; i++) @@ -219,12 +264,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - this.fingerprint = pubKey.fingerprint; + this.fingerprint = pubKey.fingerprint; this.keyId = pubKey.keyId; this.keyStrength = pubKey.keyStrength; } - internal PgpPublicKey( + internal PgpPublicKey( PublicKeyPacket publicPk, TrustPacket trustPk, IList keySigs, @@ -239,10 +284,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp this.idTrusts = idTrusts; this.idSigs = idSigs; - Init(); + Init(); } - internal PgpPublicKey( + internal PgpPublicKey( PublicKeyPacket publicPk, IList ids, IList idSigs) @@ -253,159 +298,165 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp Init(); } - /// <summary>The version of this key.</summary> + /// <summary>The version of this key.</summary> public int Version { - get { return publicPk.Version; } + get { return publicPk.Version; } } - /// <summary>The creation time of this key.</summary> - public DateTime CreationTime + /// <summary>The creation time of this key.</summary> + public DateTime CreationTime { - get { return publicPk.GetTime(); } + get { return publicPk.GetTime(); } } - /// <summary>The number of valid days from creation time - zero means no expiry.</summary> + /// <summary>The number of valid days from creation time - zero means no expiry.</summary> + /// <remarks>WARNING: This method will return 1 for keys with version > 3 that expire in less than 1 day</remarks> + [Obsolete("Use 'GetValidSeconds' instead")] public int ValidDays { - get - { - if (publicPk.Version > 3) - { - return (int)(GetValidSeconds() / (24 * 60 * 60)); - } - - return publicPk.ValidDays; - } - } - - /// <summary>Return the trust data associated with the public key, if present.</summary> - /// <returns>A byte array with trust data, null otherwise.</returns> - public byte[] GetTrustData() - { - if (trustPk == null) - { - return null; - } - - return trustPk.GetLevelAndTrustAmount(); - } - - /// <summary>The number of valid seconds from creation time - zero means no expiry.</summary> - public long GetValidSeconds() - { - if (publicPk.Version > 3) - { - if (IsMasterKey) - { - for (int i = 0; i != MasterKeyCertificationTypes.Length; i++) - { - long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]); - - if (seconds >= 0) - { - return seconds; - } - } - } - else - { - long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding); - - if (seconds >= 0) - { - return seconds; - } - } - - return 0; - } - - return (long) publicPk.ValidDays * 24 * 60 * 60; - } - - private long GetExpirationTimeFromSig( - bool selfSigned, - int signatureType) - { - foreach (PgpSignature sig in GetSignaturesOfType(signatureType)) - { - if (!selfSigned || sig.KeyId == KeyId) - { - PgpSignatureSubpacketVector hashed = sig.GetHashedSubPackets(); - - if (hashed != null) - { - return hashed.GetKeyExpirationTime(); - } - - return 0; - } - } - - return -1; - } - - /// <summary>The keyId associated with the public key.</summary> + get + { + if (publicPk.Version <= 3) + { + return publicPk.ValidDays; + } + + long expSecs = GetValidSeconds(); + if (expSecs <= 0) + return 0; + + int days = (int)(expSecs / (24 * 60 * 60)); + return System.Math.Max(1, days); + } + } + + /// <summary>Return the trust data associated with the public key, if present.</summary> + /// <returns>A byte array with trust data, null otherwise.</returns> + public byte[] GetTrustData() + { + if (trustPk == null) + { + return null; + } + + return Arrays.Clone(trustPk.GetLevelAndTrustAmount()); + } + + /// <summary>The number of valid seconds from creation time - zero means no expiry.</summary> + public long GetValidSeconds() + { + if (publicPk.Version <= 3) + { + return (long)publicPk.ValidDays * (24 * 60 * 60); + } + + if (IsMasterKey) + { + for (int i = 0; i != MasterKeyCertificationTypes.Length; i++) + { + long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]); + if (seconds >= 0) + { + return seconds; + } + } + } + else + { + long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding); + if (seconds >= 0) + { + return seconds; + } + } + + return 0; + } + + private long GetExpirationTimeFromSig( + bool selfSigned, + int signatureType) + { + foreach (PgpSignature sig in GetSignaturesOfType(signatureType)) + { + if (!selfSigned || sig.KeyId == KeyId) + { + PgpSignatureSubpacketVector hashed = sig.GetHashedSubPackets(); + + if (hashed != null) + { + return hashed.GetKeyExpirationTime(); + } + + return 0; + } + } + + return -1; + } + + /// <summary>The keyId associated with the public key.</summary> public long KeyId { get { return keyId; } } - /// <summary>The fingerprint of the key</summary> + /// <summary>The fingerprint of the key</summary> public byte[] GetFingerprint() { - return (byte[]) fingerprint.Clone(); + return (byte[]) fingerprint.Clone(); } - /// <summary> - /// Check if this key has an algorithm type that makes it suitable to use for encryption. - /// </summary> - /// <remarks> - /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for - /// determining the preferred use of the key. - /// </remarks> - /// <returns> - /// <c>true</c> if this key algorithm is suitable for encryption. - /// </returns> - public bool IsEncryptionKey + /// <summary> + /// Check if this key has an algorithm type that makes it suitable to use for encryption. + /// </summary> + /// <remarks> + /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for + /// determining the preferred use of the key. + /// </remarks> + /// <returns> + /// <c>true</c> if this key algorithm is suitable for encryption. + /// </returns> + public bool IsEncryptionKey { get { - switch (publicPk.Algorithm) - { - case PublicKeyAlgorithmTag.ElGamalEncrypt: - case PublicKeyAlgorithmTag.ElGamalGeneral: - case PublicKeyAlgorithmTag.RsaEncrypt: - case PublicKeyAlgorithmTag.RsaGeneral: - return true; - default: - return false; - } + switch (publicPk.Algorithm) + { + case PublicKeyAlgorithmTag.ECDH: + case PublicKeyAlgorithmTag.ElGamalEncrypt: + case PublicKeyAlgorithmTag.ElGamalGeneral: + case PublicKeyAlgorithmTag.RsaEncrypt: + case PublicKeyAlgorithmTag.RsaGeneral: + return true; + default: + return false; + } } } - /// <summary>True, if this is a master key.</summary> + /// <summary>True, if this is a master key.</summary> public bool IsMasterKey { get { return subSigs == null; } } - /// <summary>The algorithm code associated with the public key.</summary> + /// <summary>The algorithm code associated with the public key.</summary> public PublicKeyAlgorithmTag Algorithm { - get { return publicPk.Algorithm; } + get { return publicPk.Algorithm; } } - /// <summary>The strength of the key in bits.</summary> + /// <summary>The strength of the key in bits.</summary> public int BitStrength { get { return keyStrength; } } - /// <summary>The public key contained in the object.</summary> - /// <returns>A lightweight public key.</returns> - /// <exception cref="PgpException">If the key algorithm is not recognised.</exception> + /// <summary>The public key contained in the object.</summary> + /// <returns>A lightweight public key.</returns> + /// <exception cref="PgpException">If the key algorithm is not recognised.</exception> public AsymmetricKeyParameter GetKey() { try @@ -415,14 +466,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp case PublicKeyAlgorithmTag.RsaEncrypt: case PublicKeyAlgorithmTag.RsaGeneral: case PublicKeyAlgorithmTag.RsaSign: - RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey) publicPk.Key; + RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey)publicPk.Key; return new RsaKeyParameters(false, rsaK.Modulus, rsaK.PublicExponent); case PublicKeyAlgorithmTag.Dsa: - DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey) publicPk.Key; + DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey)publicPk.Key; return new DsaPublicKeyParameters(dsaK.Y, new DsaParameters(dsaK.P, dsaK.Q, dsaK.G)); + case PublicKeyAlgorithmTag.ECDsa: + return GetECKey("ECDSA"); + case PublicKeyAlgorithmTag.ECDH: + return GetECKey("ECDH"); case PublicKeyAlgorithmTag.ElGamalEncrypt: case PublicKeyAlgorithmTag.ElGamalGeneral: - ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey) publicPk.Key; + ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey)publicPk.Key; return new ElGamalPublicKeyParameters(elK.Y, new ElGamalParameters(elK.P, elK.G)); default: throw new PgpException("unknown public key algorithm encountered"); @@ -438,50 +493,58 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - /// <summary>Allows enumeration of any user IDs associated with the key.</summary> - /// <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns> + private ECPublicKeyParameters GetECKey(string algorithm) + { + ECPublicBcpgKey ecK = (ECPublicBcpgKey)publicPk.Key; + X9ECParameters x9 = ECKeyPairGenerator.FindECCurveByOid(ecK.CurveOid); + ECPoint q = x9.Curve.DecodePoint(BigIntegers.AsUnsignedByteArray(ecK.EncodedPoint)); + return new ECPublicKeyParameters(algorithm, q, ecK.CurveOid); + } + + /// <summary>Allows enumeration of any user IDs associated with the key.</summary> + /// <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns> public IEnumerable GetUserIds() { IList temp = Platform.CreateArrayList(); - foreach (object o in ids) - { - if (o is string) - { - temp.Add(o); + foreach (object o in ids) + { + if (o is string) + { + temp.Add(o); } } - return new EnumerableProxy(temp); + return new EnumerableProxy(temp); } - /// <summary>Allows enumeration of any user attribute vectors associated with the key.</summary> - /// <returns>An <c>IEnumerable</c> of <c>PgpUserAttributeSubpacketVector</c> objects.</returns> + /// <summary>Allows enumeration of any user attribute vectors associated with the key.</summary> + /// <returns>An <c>IEnumerable</c> of <c>PgpUserAttributeSubpacketVector</c> objects.</returns> public IEnumerable GetUserAttributes() { IList temp = Platform.CreateArrayList(); - foreach (object o in ids) - { - if (o is PgpUserAttributeSubpacketVector) - { - temp.Add(o); - } - } + foreach (object o in ids) + { + if (o is PgpUserAttributeSubpacketVector) + { + temp.Add(o); + } + } - return new EnumerableProxy(temp); + return new EnumerableProxy(temp); } - /// <summary>Allows enumeration of any signatures associated with the passed in id.</summary> - /// <param name="id">The ID to be matched.</param> - /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns> + /// <summary>Allows enumeration of any signatures associated with the passed in id.</summary> + /// <param name="id">The ID to be matched.</param> + /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns> public IEnumerable GetSignaturesForId( string id) { - if (id == null) - throw new ArgumentNullException("id"); + if (id == null) + throw new ArgumentNullException("id"); - for (int i = 0; i != ids.Count; i++) + for (int i = 0; i != ids.Count; i++) { if (id.Equals(ids[i])) { @@ -489,12 +552,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - return null; + return null; } - /// <summary>Allows enumeration of signatures associated with the passed in user attributes.</summary> - /// <param name="userAttributes">The vector of user attributes to be matched.</param> - /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns> + /// <summary>Allows enumeration of signatures associated with the passed in user attributes.</summary> + /// <param name="userAttributes">The vector of user attributes to be matched.</param> + /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns> public IEnumerable GetSignaturesForUserAttribute( PgpUserAttributeSubpacketVector userAttributes) { @@ -506,18 +569,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - return null; + return null; } - /// <summary>Allows enumeration of signatures of the passed in type that are on this key.</summary> - /// <param name="signatureType">The type of the signature to be returned.</param> - /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns> + /// <summary>Allows enumeration of signatures of the passed in type that are on this key.</summary> + /// <param name="signatureType">The type of the signature to be returned.</param> + /// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns> public IEnumerable GetSignaturesOfType( int signatureType) { IList temp = Platform.CreateArrayList(); - foreach (PgpSignature sig in GetSignatures()) + foreach (PgpSignature sig in GetSignatures()) { if (sig.SignatureType == signatureType) { @@ -525,63 +588,79 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - return new EnumerableProxy(temp); + return new EnumerableProxy(temp); } - /// <summary>Allows enumeration of all signatures/certifications associated with this key.</summary> - /// <returns>An <c>IEnumerable</c> with all signatures/certifications.</returns> + /// <summary>Allows enumeration of all signatures/certifications associated with this key.</summary> + /// <returns>An <c>IEnumerable</c> with all signatures/certifications.</returns> public IEnumerable GetSignatures() { - IList sigs; - if (subSigs != null) - { - sigs = subSigs; - } - else - { + IList sigs = subSigs; + if (sigs == null) + { sigs = Platform.CreateArrayList(keySigs); - foreach (ICollection extraSigs in idSigs) - { + foreach (ICollection extraSigs in idSigs) + { CollectionUtilities.AddRange(sigs, extraSigs); - } - } + } + } + + return new EnumerableProxy(sigs); + } - return new EnumerableProxy(sigs); + /** + * Return all signatures/certifications directly associated with this key (ie, not to a user id). + * + * @return an iterator (possibly empty) with all signatures/certifications. + */ + public IEnumerable GetKeySignatures() + { + IList sigs = subSigs; + if (sigs == null) + { + sigs = Platform.CreateArrayList(keySigs); + } + return new EnumerableProxy(sigs); } - public byte[] GetEncoded() + public PublicKeyPacket PublicKeyPacket + { + get { return publicPk; } + } + + public byte[] GetEncoded() { MemoryStream bOut = new MemoryStream(); Encode(bOut); return bOut.ToArray(); } - public void Encode( + public void Encode( Stream outStr) { BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr); - bcpgOut.WritePacket(publicPk); + bcpgOut.WritePacket(publicPk); if (trustPk != null) { bcpgOut.WritePacket(trustPk); } - if (subSigs == null) // not a sub-key + if (subSigs == null) // not a sub-key { - foreach (PgpSignature keySig in keySigs) - { - keySig.Encode(bcpgOut); - } + foreach (PgpSignature keySig in keySigs) + { + keySig.Encode(bcpgOut); + } - for (int i = 0; i != ids.Count; i++) + for (int i = 0; i != ids.Count; i++) { if (ids[i] is string) { string id = (string) ids[i]; - bcpgOut.WritePacket(new UserIdPacket(id)); + bcpgOut.WritePacket(new UserIdPacket(id)); } else { @@ -589,28 +668,28 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray())); } - if (idTrusts[i] != null) + if (idTrusts[i] != null) { bcpgOut.WritePacket((ContainedPacket)idTrusts[i]); } - foreach (PgpSignature sig in (IList) idSigs[i]) - { - sig.Encode(bcpgOut); - } + foreach (PgpSignature sig in (IList) idSigs[i]) + { + sig.Encode(bcpgOut); + } } } else { - foreach (PgpSignature subSig in subSigs) - { - subSig.Encode(bcpgOut); - } + foreach (PgpSignature subSig in subSigs) + { + subSig.Encode(bcpgOut); + } } } - /// <summary>Check whether this (sub)key has a revocation signature on it.</summary> - /// <returns>True, if this (sub)key has been revoked.</returns> + /// <summary>Check whether this (sub)key has a revocation signature on it.</summary> + /// <returns>True, if this (sub)key has been revoked.</returns> public bool IsRevoked() { int ns = 0; @@ -638,98 +717,98 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp return revoked; } - /// <summary>Add a certification for an id to the given public key.</summary> - /// <param name="key">The key the certification is to be added to.</param> - /// <param name="id">The ID the certification is associated with.</param> - /// <param name="certification">The new certification.</param> - /// <returns>The re-certified key.</returns> + /// <summary>Add a certification for an id to the given public key.</summary> + /// <param name="key">The key the certification is to be added to.</param> + /// <param name="id">The ID the certification is associated with.</param> + /// <param name="certification">The new certification.</param> + /// <returns>The re-certified key.</returns> public static PgpPublicKey AddCertification( PgpPublicKey key, string id, PgpSignature certification) { - return AddCert(key, id, certification); - } - - /// <summary>Add a certification for the given UserAttributeSubpackets to the given public key.</summary> - /// <param name="key">The key the certification is to be added to.</param> - /// <param name="userAttributes">The attributes the certification is associated with.</param> - /// <param name="certification">The new certification.</param> - /// <returns>The re-certified key.</returns> - public static PgpPublicKey AddCertification( - PgpPublicKey key, - PgpUserAttributeSubpacketVector userAttributes, - PgpSignature certification) - { - return AddCert(key, userAttributes, certification); - } - - private static PgpPublicKey AddCert( - PgpPublicKey key, - object id, - PgpSignature certification) - { - PgpPublicKey returnKey = new PgpPublicKey(key); - IList sigList = null; - - for (int i = 0; i != returnKey.ids.Count; i++) - { - if (id.Equals(returnKey.ids[i])) - { - sigList = (IList) returnKey.idSigs[i]; - } - } - - if (sigList != null) - { - sigList.Add(certification); - } - else - { - sigList = Platform.CreateArrayList(); - sigList.Add(certification); - returnKey.ids.Add(id); - returnKey.idTrusts.Add(null); - returnKey.idSigs.Add(sigList); - } - - return returnKey; - } - - /// <summary> - /// Remove any certifications associated with a user attribute subpacket on a key. - /// </summary> - /// <param name="key">The key the certifications are to be removed from.</param> - /// <param name="userAttributes">The attributes to be removed.</param> - /// <returns> - /// The re-certified key, or null if the user attribute subpacket was not found on the key. - /// </returns> - public static PgpPublicKey RemoveCertification( - PgpPublicKey key, - PgpUserAttributeSubpacketVector userAttributes) - { - return RemoveCert(key, userAttributes); - } - - /// <summary>Remove any certifications associated with a given ID on a key.</summary> - /// <param name="key">The key the certifications are to be removed from.</param> - /// <param name="id">The ID that is to be removed.</param> - /// <returns>The re-certified key, or null if the ID was not found on the key.</returns> + return AddCert(key, id, certification); + } + + /// <summary>Add a certification for the given UserAttributeSubpackets to the given public key.</summary> + /// <param name="key">The key the certification is to be added to.</param> + /// <param name="userAttributes">The attributes the certification is associated with.</param> + /// <param name="certification">The new certification.</param> + /// <returns>The re-certified key.</returns> + public static PgpPublicKey AddCertification( + PgpPublicKey key, + PgpUserAttributeSubpacketVector userAttributes, + PgpSignature certification) + { + return AddCert(key, userAttributes, certification); + } + + private static PgpPublicKey AddCert( + PgpPublicKey key, + object id, + PgpSignature certification) + { + PgpPublicKey returnKey = new PgpPublicKey(key); + IList sigList = null; + + for (int i = 0; i != returnKey.ids.Count; i++) + { + if (id.Equals(returnKey.ids[i])) + { + sigList = (IList) returnKey.idSigs[i]; + } + } + + if (sigList != null) + { + sigList.Add(certification); + } + else + { + sigList = Platform.CreateArrayList(); + sigList.Add(certification); + returnKey.ids.Add(id); + returnKey.idTrusts.Add(null); + returnKey.idSigs.Add(sigList); + } + + return returnKey; + } + + /// <summary> + /// Remove any certifications associated with a user attribute subpacket on a key. + /// </summary> + /// <param name="key">The key the certifications are to be removed from.</param> + /// <param name="userAttributes">The attributes to be removed.</param> + /// <returns> + /// The re-certified key, or null if the user attribute subpacket was not found on the key. + /// </returns> + public static PgpPublicKey RemoveCertification( + PgpPublicKey key, + PgpUserAttributeSubpacketVector userAttributes) + { + return RemoveCert(key, userAttributes); + } + + /// <summary>Remove any certifications associated with a given ID on a key.</summary> + /// <param name="key">The key the certifications are to be removed from.</param> + /// <param name="id">The ID that is to be removed.</param> + /// <returns>The re-certified key, or null if the ID was not found on the key.</returns> public static PgpPublicKey RemoveCertification( PgpPublicKey key, string id) { - return RemoveCert(key, id); - } + return RemoveCert(key, id); + } - private static PgpPublicKey RemoveCert( - PgpPublicKey key, - object id) - { - PgpPublicKey returnKey = new PgpPublicKey(key); + private static PgpPublicKey RemoveCert( + PgpPublicKey key, + object id) + { + PgpPublicKey returnKey = new PgpPublicKey(key); bool found = false; - for (int i = 0; i < returnKey.ids.Count; i++) + for (int i = 0; i < returnKey.ids.Count; i++) { if (id.Equals(returnKey.ids[i])) { @@ -740,64 +819,64 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - return found ? returnKey : null; + return found ? returnKey : null; } - /// <summary>Remove a certification associated with a given ID on a key.</summary> - /// <param name="key">The key the certifications are to be removed from.</param> - /// <param name="id">The ID that the certfication is to be removed from.</param> - /// <param name="certification">The certfication to be removed.</param> - /// <returns>The re-certified key, or null if the certification was not found.</returns> + /// <summary>Remove a certification associated with a given ID on a key.</summary> + /// <param name="key">The key the certifications are to be removed from.</param> + /// <param name="id">The ID that the certfication is to be removed from.</param> + /// <param name="certification">The certfication to be removed.</param> + /// <returns>The re-certified key, or null if the certification was not found.</returns> public static PgpPublicKey RemoveCertification( PgpPublicKey key, string id, PgpSignature certification) { - return RemoveCert(key, id, certification); - } - - /// <summary>Remove a certification associated with a given user attributes on a key.</summary> - /// <param name="key">The key the certifications are to be removed from.</param> - /// <param name="userAttributes">The user attributes that the certfication is to be removed from.</param> - /// <param name="certification">The certification to be removed.</param> - /// <returns>The re-certified key, or null if the certification was not found.</returns> - public static PgpPublicKey RemoveCertification( - PgpPublicKey key, - PgpUserAttributeSubpacketVector userAttributes, - PgpSignature certification) - { - return RemoveCert(key, userAttributes, certification); - } - - private static PgpPublicKey RemoveCert( - PgpPublicKey key, - object id, - PgpSignature certification) - { - PgpPublicKey returnKey = new PgpPublicKey(key); + return RemoveCert(key, id, certification); + } + + /// <summary>Remove a certification associated with a given user attributes on a key.</summary> + /// <param name="key">The key the certifications are to be removed from.</param> + /// <param name="userAttributes">The user attributes that the certfication is to be removed from.</param> + /// <param name="certification">The certification to be removed.</param> + /// <returns>The re-certified key, or null if the certification was not found.</returns> + public static PgpPublicKey RemoveCertification( + PgpPublicKey key, + PgpUserAttributeSubpacketVector userAttributes, + PgpSignature certification) + { + return RemoveCert(key, userAttributes, certification); + } + + private static PgpPublicKey RemoveCert( + PgpPublicKey key, + object id, + PgpSignature certification) + { + PgpPublicKey returnKey = new PgpPublicKey(key); bool found = false; - for (int i = 0; i < returnKey.ids.Count; i++) + for (int i = 0; i < returnKey.ids.Count; i++) { if (id.Equals(returnKey.ids[i])) { IList certs = (IList) returnKey.idSigs[i]; found = certs.Contains(certification); - if (found) - { - certs.Remove(certification); - } + if (found) + { + certs.Remove(certification); + } } } - return found ? returnKey : null; + return found ? returnKey : null; } - /// <summary>Add a revocation or some other key certification to a key.</summary> - /// <param name="key">The key the revocation is to be added to.</param> - /// <param name="certification">The key signature to be added.</param> - /// <returns>The new changed public key object.</returns> + /// <summary>Add a revocation or some other key certification to a key.</summary> + /// <param name="key">The key the revocation is to be added to.</param> + /// <param name="certification">The key signature to be added.</param> + /// <returns>The new changed public key object.</returns> public static PgpPublicKey AddCertification( PgpPublicKey key, PgpSignature certification) @@ -817,9 +896,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp } } - PgpPublicKey returnKey = new PgpPublicKey(key); + PgpPublicKey returnKey = new PgpPublicKey(key); - if (returnKey.subSigs != null) + if (returnKey.subSigs != null) { returnKey.subSigs.Add(certification); } @@ -828,63 +907,63 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp returnKey.keySigs.Add(certification); } - return returnKey; + return returnKey; } - /// <summary>Remove a certification from the key.</summary> - /// <param name="key">The key the certifications are to be removed from.</param> - /// <param name="certification">The certfication to be removed.</param> - /// <returns>The modified key, null if the certification was not found.</returns> - public static PgpPublicKey RemoveCertification( - PgpPublicKey key, - PgpSignature certification) - { - PgpPublicKey returnKey = new PgpPublicKey(key); - IList sigs = returnKey.subSigs != null - ? returnKey.subSigs - : returnKey.keySigs; + /// <summary>Remove a certification from the key.</summary> + /// <param name="key">The key the certifications are to be removed from.</param> + /// <param name="certification">The certfication to be removed.</param> + /// <returns>The modified key, null if the certification was not found.</returns> + public static PgpPublicKey RemoveCertification( + PgpPublicKey key, + PgpSignature certification) + { + PgpPublicKey returnKey = new PgpPublicKey(key); + IList sigs = returnKey.subSigs != null + ? returnKey.subSigs + : returnKey.keySigs; // bool found = sigs.Remove(certification); - int pos = sigs.IndexOf(certification); - bool found = pos >= 0; - - if (found) - { - sigs.RemoveAt(pos); - } - else - { - foreach (String id in key.GetUserIds()) - { - foreach (object sig in key.GetSignaturesForId(id)) - { - // TODO Is this the right type of equality test? - if (certification == sig) - { - found = true; - returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification); - } - } - } - - if (!found) - { - foreach (PgpUserAttributeSubpacketVector id in key.GetUserAttributes()) - { - foreach (object sig in key.GetSignaturesForUserAttribute(id)) - { - // TODO Is this the right type of equality test? - if (certification == sig) - { - found = true; - returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification); - } - } - } - } - } - - return returnKey; - } - } + int pos = sigs.IndexOf(certification); + bool found = pos >= 0; + + if (found) + { + sigs.RemoveAt(pos); + } + else + { + foreach (String id in key.GetUserIds()) + { + foreach (object sig in key.GetSignaturesForId(id)) + { + // TODO Is this the right type of equality test? + if (certification == sig) + { + found = true; + returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification); + } + } + } + + if (!found) + { + foreach (PgpUserAttributeSubpacketVector id in key.GetUserAttributes()) + { + foreach (object sig in key.GetSignaturesForUserAttribute(id)) + { + // TODO Is this the right type of equality test? + if (certification == sig) + { + found = true; + returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification); + } + } + } + } + } + + return returnKey; + } + } }