summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpSecretKeyRing.cs
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2014-02-25 17:16:34 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2014-02-25 17:16:34 +0700
commita6039dfa9392ca64a3b0efe591aaf7b8441d13fc (patch)
tree8fcf9779569fe77fd0e65757ccce44345fc6fa92 /crypto/src/openpgp/PgpSecretKeyRing.cs
parentCheck a few more points in the encoding test (diff)
downloadBouncyCastle.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.cs377
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;
         }
     }
 }