diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-02-25 17:16:34 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2014-02-25 17:16:34 +0700 |
commit | a6039dfa9392ca64a3b0efe591aaf7b8441d13fc (patch) | |
tree | 8fcf9779569fe77fd0e65757ccce44345fc6fa92 /crypto/src/openpgp/PgpSecretKeyRing.cs | |
parent | Check a few more points in the encoding test (diff) | |
download | BouncyCastle.NET-ed25519-a6039dfa9392ca64a3b0efe591aaf7b8441d13fc.tar.xz |
Port some openpgp updates from Java build for secret keys
Diffstat (limited to 'crypto/src/openpgp/PgpSecretKeyRing.cs')
-rw-r--r-- | crypto/src/openpgp/PgpSecretKeyRing.cs | 377 |
1 files changed, 192 insertions, 185 deletions
diff --git a/crypto/src/openpgp/PgpSecretKeyRing.cs b/crypto/src/openpgp/PgpSecretKeyRing.cs index 3e646eaa1..70cd7217c 100644 --- a/crypto/src/openpgp/PgpSecretKeyRing.cs +++ b/crypto/src/openpgp/PgpSecretKeyRing.cs @@ -8,57 +8,57 @@ using Org.BouncyCastle.Utilities.Collections; namespace Org.BouncyCastle.Bcpg.OpenPgp { - /// <remarks> - /// Class to hold a single master secret key and its subkeys. - /// <p> - /// Often PGP keyring files consist of multiple master keys, if you are trying to process - /// or construct one of these you should use the <c>PgpSecretKeyRingBundle</c> class. - /// </p> - /// </remarks> - public class PgpSecretKeyRing - : PgpKeyRing + /// <remarks> + /// Class to hold a single master secret key and its subkeys. + /// <p> + /// Often PGP keyring files consist of multiple master keys, if you are trying to process + /// or construct one of these you should use the <c>PgpSecretKeyRingBundle</c> class. + /// </p> + /// </remarks> + public class PgpSecretKeyRing + : PgpKeyRing { private readonly IList keys; - private readonly IList extraPubKeys; - - internal PgpSecretKeyRing( - IList keys) - : this(keys, Platform.CreateArrayList()) - { - } - - private PgpSecretKeyRing( - IList keys, - IList extraPubKeys) - { - this.keys = keys; - this.extraPubKeys = extraPubKeys; - } - - public PgpSecretKeyRing( + private readonly IList extraPubKeys; + + internal PgpSecretKeyRing( + IList keys) + : this(keys, Platform.CreateArrayList()) + { + } + + private PgpSecretKeyRing( + IList keys, + IList extraPubKeys) + { + this.keys = keys; + this.extraPubKeys = extraPubKeys; + } + + public PgpSecretKeyRing( byte[] encoding) : this(new MemoryStream(encoding)) { } - public PgpSecretKeyRing( + public PgpSecretKeyRing( Stream inputStream) { - this.keys = Platform.CreateArrayList(); + this.keys = Platform.CreateArrayList(); this.extraPubKeys = Platform.CreateArrayList(); - BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream); + BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream); - PacketTag initialTag = bcpgInput.NextPacketTag(); - if (initialTag != PacketTag.SecretKey && initialTag != PacketTag.SecretSubkey) + PacketTag initialTag = bcpgInput.NextPacketTag(); + if (initialTag != PacketTag.SecretKey && initialTag != PacketTag.SecretSubkey) { throw new IOException("secret key ring doesn't start with secret key tag: " - + "tag 0x" + ((int)initialTag).ToString("X")); + + "tag 0x" + ((int)initialTag).ToString("X")); } - SecretKeyPacket secret = (SecretKeyPacket) bcpgInput.ReadPacket(); + SecretKeyPacket secret = (SecretKeyPacket) bcpgInput.ReadPacket(); - // + // // ignore GPG comment packets if found. // while (bcpgInput.NextPacketTag() == PacketTag.Experimental2) @@ -66,65 +66,65 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp bcpgInput.ReadPacket(); } - TrustPacket trust = ReadOptionalTrustPacket(bcpgInput); + TrustPacket trust = ReadOptionalTrustPacket(bcpgInput); - // revocation and direct signatures - IList keySigs = ReadSignaturesAndTrust(bcpgInput); + // revocation and direct signatures + IList keySigs = ReadSignaturesAndTrust(bcpgInput); - IList ids, idTrusts, idSigs; - ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs); + IList ids, idTrusts, idSigs; + ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs); - keys.Add(new PgpSecretKey(secret, new PgpPublicKey(secret.PublicKeyPacket, trust, keySigs, ids, idTrusts, idSigs))); + keys.Add(new PgpSecretKey(secret, new PgpPublicKey(secret.PublicKeyPacket, trust, keySigs, ids, idTrusts, idSigs))); - // Read subkeys - while (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey - || bcpgInput.NextPacketTag() == PacketTag.PublicSubkey) + // Read subkeys + while (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey + || bcpgInput.NextPacketTag() == PacketTag.PublicSubkey) { - if (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey) - { - SecretSubkeyPacket sub = (SecretSubkeyPacket) bcpgInput.ReadPacket(); - - // - // ignore GPG comment packets if found. - // - while (bcpgInput.NextPacketTag() == PacketTag.Experimental2) - { - bcpgInput.ReadPacket(); - } - - TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput); - IList sigList = ReadSignaturesAndTrust(bcpgInput); - - keys.Add(new PgpSecretKey(sub, new PgpPublicKey(sub.PublicKeyPacket, subTrust, sigList))); - } - else - { - PublicSubkeyPacket sub = (PublicSubkeyPacket) bcpgInput.ReadPacket(); - - TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput); - IList sigList = ReadSignaturesAndTrust(bcpgInput); - - extraPubKeys.Add(new PgpPublicKey(sub, subTrust, sigList)); - } + if (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey) + { + SecretSubkeyPacket sub = (SecretSubkeyPacket) bcpgInput.ReadPacket(); + + // + // ignore GPG comment packets if found. + // + while (bcpgInput.NextPacketTag() == PacketTag.Experimental2) + { + bcpgInput.ReadPacket(); + } + + TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput); + IList sigList = ReadSignaturesAndTrust(bcpgInput); + + keys.Add(new PgpSecretKey(sub, new PgpPublicKey(sub.PublicKeyPacket, subTrust, sigList))); + } + else + { + PublicSubkeyPacket sub = (PublicSubkeyPacket) bcpgInput.ReadPacket(); + + TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput); + IList sigList = ReadSignaturesAndTrust(bcpgInput); + + extraPubKeys.Add(new PgpPublicKey(sub, subTrust, sigList)); + } } } - /// <summary>Return the public key for the master key.</summary> + /// <summary>Return the public key for the master key.</summary> public PgpPublicKey GetPublicKey() { return ((PgpSecretKey) keys[0]).PublicKey; } - /// <summary>Return the master private key.</summary> + /// <summary>Return the master private key.</summary> public PgpSecretKey GetSecretKey() { return (PgpSecretKey) keys[0]; } - /// <summary>Allows enumeration of the secret keys.</summary> - /// <returns>An <c>IEnumerable</c> of <c>PgpSecretKey</c> objects.</returns> - public IEnumerable GetSecretKeys() + /// <summary>Allows enumeration of the secret keys.</summary> + /// <returns>An <c>IEnumerable</c> of <c>PgpSecretKey</c> objects.</returns> + public IEnumerable GetSecretKeys() { return new EnumerableProxy(keys); } @@ -132,29 +132,29 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp public PgpSecretKey GetSecretKey( long keyId) { - foreach (PgpSecretKey k in keys) - { - if (keyId == k.KeyId) - { - return k; - } - } - - return null; + foreach (PgpSecretKey k in keys) + { + if (keyId == k.KeyId) + { + 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 + /// appears in this fashion. + /// </summary> + /// <returns>An <c>IEnumerable</c> of unattached, or extra, public keys.</returns> + public IEnumerable GetExtraPublicKeys() + { + return new EnumerableProxy(extraPubKeys); } - /// <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 - /// appears in this fashion. - /// </summary> - /// <returns>An <c>IEnumerable</c> of unattached, or extra, public keys.</returns> - public IEnumerable GetExtraPublicKeys() - { - return new EnumerableProxy(extraPubKeys); - } - - public byte[] GetEncoded() + public byte[] GetEncoded() { MemoryStream bOut = new MemoryStream(); @@ -166,117 +166,124 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp public void Encode( Stream outStr) { - if (outStr == null) - throw new ArgumentNullException("outStr"); - - foreach (PgpSecretKey key in keys) - { - key.Encode(outStr); - } - foreach (PgpPublicKey extraPubKey in extraPubKeys) - { - extraPubKey.Encode(outStr); - } + if (outStr == null) + throw new ArgumentNullException("outStr"); + + foreach (PgpSecretKey key in keys) + { + key.Encode(outStr); + } + foreach (PgpPublicKey extraPubKey in extraPubKeys) + { + extraPubKey.Encode(outStr); + } } - /// <summary> - /// Replace the public key set on the secret ring with the corresponding key off the public ring. - /// </summary> - /// <param name="secretRing">Secret ring to be changed.</param> - /// <param name="publicRing">Public ring containing the new public key set.</param> - public static PgpSecretKeyRing ReplacePublicKeys( - PgpSecretKeyRing secretRing, - PgpPublicKeyRing publicRing) - { + /// <summary> + /// Replace the public key set on the secret ring with the corresponding key off the public ring. + /// </summary> + /// <param name="secretRing">Secret ring to be changed.</param> + /// <param name="publicRing">Public ring containing the new public key set.</param> + public static PgpSecretKeyRing ReplacePublicKeys( + PgpSecretKeyRing secretRing, + PgpPublicKeyRing publicRing) + { IList newList = Platform.CreateArrayList(secretRing.keys.Count); - foreach (PgpSecretKey sk in secretRing.keys) - { - PgpPublicKey pk = publicRing.GetPublicKey(sk.KeyId); - - newList.Add(PgpSecretKey.ReplacePublicKey(sk, pk)); - } - - return new PgpSecretKeyRing(newList); - } - - /// <summary> - /// Return a copy of the passed in secret key ring, with the master key and sub keys encrypted - /// using a new password and the passed in algorithm. - /// </summary> - /// <param name="ring">The <c>PgpSecretKeyRing</c> to be copied.</param> - /// <param name="oldPassPhrase">The current password for key.</param> - /// <param name="newPassPhrase">The new password for the key.</param> - /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param> - /// <param name="rand">Source of randomness.</param> - public static PgpSecretKeyRing CopyWithNewPassword( - PgpSecretKeyRing ring, - char[] oldPassPhrase, - char[] newPassPhrase, - SymmetricKeyAlgorithmTag newEncAlgorithm, - SecureRandom rand) - { + foreach (PgpSecretKey sk in secretRing.keys) + { + PgpPublicKey pk = publicRing.GetPublicKey(sk.KeyId); + + newList.Add(PgpSecretKey.ReplacePublicKey(sk, pk)); + } + + return new PgpSecretKeyRing(newList); + } + + /// <summary> + /// Return a copy of the passed in secret key ring, with the master key and sub keys encrypted + /// using a new password and the passed in algorithm. + /// </summary> + /// <param name="ring">The <c>PgpSecretKeyRing</c> to be copied.</param> + /// <param name="oldPassPhrase">The current password for key.</param> + /// <param name="newPassPhrase">The new password for the key.</param> + /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param> + /// <param name="rand">Source of randomness.</param> + public static PgpSecretKeyRing CopyWithNewPassword( + PgpSecretKeyRing ring, + char[] oldPassPhrase, + char[] newPassPhrase, + SymmetricKeyAlgorithmTag newEncAlgorithm, + SecureRandom rand) + { IList newKeys = Platform.CreateArrayList(ring.keys.Count); - foreach (PgpSecretKey secretKey in ring.GetSecretKeys()) - { - newKeys.Add(PgpSecretKey.CopyWithNewPassword(secretKey, oldPassPhrase, newPassPhrase, newEncAlgorithm, rand)); - } - - return new PgpSecretKeyRing(newKeys, ring.extraPubKeys); - } - - /// <summary> - /// Returns a new key ring with the secret key passed in either added or - /// replacing an existing one with the same key ID. - /// </summary> - /// <param name="secRing">The secret key ring to be modified.</param> - /// <param name="secKey">The secret key to be inserted.</param> - /// <returns>A new <c>PgpSecretKeyRing</c></returns> - public static PgpSecretKeyRing InsertSecretKey( + foreach (PgpSecretKey secretKey in ring.GetSecretKeys()) + { + if (secretKey.IsPrivateKeyEmpty) + { + newKeys.Add(secretKey); + } + else + { + newKeys.Add(PgpSecretKey.CopyWithNewPassword(secretKey, oldPassPhrase, newPassPhrase, newEncAlgorithm, rand)); + } + } + + return new PgpSecretKeyRing(newKeys, ring.extraPubKeys); + } + + /// <summary> + /// Returns a new key ring with the secret key passed in either added or + /// replacing an existing one with the same key ID. + /// </summary> + /// <param name="secRing">The secret key ring to be modified.</param> + /// <param name="secKey">The secret key to be inserted.</param> + /// <returns>A new <c>PgpSecretKeyRing</c></returns> + public static PgpSecretKeyRing InsertSecretKey( PgpSecretKeyRing secRing, PgpSecretKey secKey) { IList keys = Platform.CreateArrayList(secRing.keys); bool found = false; - bool masterFound = false; + bool masterFound = false; - for (int i = 0; i != keys.Count; i++) + for (int i = 0; i != keys.Count; i++) { PgpSecretKey key = (PgpSecretKey) keys[i]; - if (key.KeyId == secKey.KeyId) + if (key.KeyId == secKey.KeyId) { found = true; keys[i] = secKey; } - if (key.IsMasterKey) - { - masterFound = true; - } - } + if (key.IsMasterKey) + { + masterFound = true; + } + } if (!found) { - if (secKey.IsMasterKey) - { - if (masterFound) - throw new ArgumentException("cannot add a master key to a ring that already has one"); - - keys.Insert(0, secKey); - } - else - { - keys.Add(secKey); - } + if (secKey.IsMasterKey) + { + if (masterFound) + throw new ArgumentException("cannot add a master key to a ring that already has one"); + + keys.Insert(0, secKey); + } + else + { + keys.Add(secKey); + } } - return new PgpSecretKeyRing(keys, secRing.extraPubKeys); - } + return new PgpSecretKeyRing(keys, secRing.extraPubKeys); + } - /// <summary>Returns a new key ring with the secret key passed in removed from the key ring.</summary> - /// <param name="secRing">The secret key ring to be modified.</param> - /// <param name="secKey">The secret key to be removed.</param> - /// <returns>A new <c>PgpSecretKeyRing</c>, or null if secKey is not found.</returns> + /// <summary>Returns a new key ring with the secret key passed in removed from the key ring.</summary> + /// <param name="secRing">The secret key ring to be modified.</param> + /// <param name="secKey">The secret key to be removed.</param> + /// <returns>A new <c>PgpSecretKeyRing</c>, or null if secKey is not found.</returns> public static PgpSecretKeyRing RemoveSecretKey( PgpSecretKeyRing secRing, PgpSecretKey secKey) @@ -284,18 +291,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp IList keys = Platform.CreateArrayList(secRing.keys); bool found = false; - for (int i = 0; i < keys.Count; i++) + for (int i = 0; i < keys.Count; i++) { PgpSecretKey key = (PgpSecretKey)keys[i]; - if (key.KeyId == secKey.KeyId) + if (key.KeyId == secKey.KeyId) { found = true; keys.RemoveAt(i); } } - return found ? new PgpSecretKeyRing(keys, secRing.extraPubKeys) : null; + return found ? new PgpSecretKeyRing(keys, secRing.extraPubKeys) : null; } } } |