summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpSecretKey.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/openpgp/PgpSecretKey.cs')
-rw-r--r--crypto/src/openpgp/PgpSecretKey.cs346
1 files changed, 306 insertions, 40 deletions
diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs
index 1027393ce..0f472c1a4 100644
--- a/crypto/src/openpgp/PgpSecretKey.cs
+++ b/crypto/src/openpgp/PgpSecretKey.cs
@@ -30,18 +30,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             PgpPrivateKey				privKey,
             PgpPublicKey				pubKey,
             SymmetricKeyAlgorithmTag	encAlgorithm,
-            char[]						passPhrase,
-            bool						useSha1,
-            SecureRandom				rand)
-            : this(privKey, pubKey, encAlgorithm, passPhrase, useSha1, rand, false)
-        {
-        }
-
-        internal PgpSecretKey(
-            PgpPrivateKey				privKey,
-            PgpPublicKey				pubKey,
-            SymmetricKeyAlgorithmTag	encAlgorithm,
-            char[]						passPhrase,
+            byte[]						rawPassPhrase,
+            bool                        clearPassPhrase,
             bool						useSha1,
             SecureRandom				rand,
             bool						isMasterKey)
@@ -107,7 +97,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                     byte[] encData;
                     if (pub.Version >= 4)
                     {
-                        encData = EncryptKeyData(keyData, encAlgorithm, passPhrase, rand, out s2k, out iv);
+                        encData = EncryptKeyData(keyData, encAlgorithm, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv);
                     }
                     else
                     {
@@ -139,6 +129,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             }
         }
 
+        /// <remarks>
+        /// Conversion of the passphrase characters to bytes is performed using Convert.ToByte(), which is
+        /// the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
+        [Obsolete("Use the constructor taking an explicit 'useSha1' parameter instead")]
         public PgpSecretKey(
             int							certificationLevel,
             PgpKeyPair					keyPair,
@@ -152,32 +147,151 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         {
         }
 
+        /// <remarks>
+        /// Conversion of the passphrase characters to bytes is performed using Convert.ToByte(), which is
+        /// the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
+        public PgpSecretKey(
+            int							certificationLevel,
+            PgpKeyPair					keyPair,
+            string						id,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+            bool						useSha1,
+            PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets,
+            SecureRandom				rand)
+            : this(certificationLevel, keyPair, id, encAlgorithm, false, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
+        {
+        }
+
+        /// <remarks>
+        /// If utf8PassPhrase is true, conversion of the passphrase to bytes uses Encoding.UTF8.GetBytes(), otherwise the conversion
+        /// is performed using Convert.ToByte(), which is the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
         public PgpSecretKey(
             int							certificationLevel,
             PgpKeyPair					keyPair,
             string						id,
             SymmetricKeyAlgorithmTag	encAlgorithm,
+            bool                        utf8PassPhrase,
             char[]						passPhrase,
             bool						useSha1,
             PgpSignatureSubpacketVector	hashedPackets,
             PgpSignatureSubpacketVector	unhashedPackets,
             SecureRandom				rand)
-            : this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets), encAlgorithm, passPhrase, useSha1, rand, true)
+            : this(certificationLevel, keyPair, id, encAlgorithm,
+                PgpUtilities.EncodePassPhrase(passPhrase, utf8PassPhrase), true,
+                useSha1, hashedPackets, unhashedPackets, rand)
+        {
+        }
+
+        /// <remarks>
+        /// Allows the caller to handle the encoding of the passphrase to bytes.
+        /// </remarks>
+        public PgpSecretKey(
+            int							certificationLevel,
+            PgpKeyPair					keyPair,
+            string						id,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            byte[]						rawPassPhrase,
+            bool						useSha1,
+            PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets,
+            SecureRandom				rand)
+            : this(certificationLevel, keyPair, id, encAlgorithm, rawPassPhrase, false, useSha1, hashedPackets, unhashedPackets, rand)
+        {
+        }
+
+        internal PgpSecretKey(
+            int							certificationLevel,
+            PgpKeyPair					keyPair,
+            string						id,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            byte[]						rawPassPhrase,
+            bool                        clearPassPhrase,
+            bool						useSha1,
+            PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets,
+            SecureRandom				rand)
+            : this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets),
+                encAlgorithm, rawPassPhrase, clearPassPhrase, useSha1, rand, true)
+        {
+        }
+
+        /// <remarks>
+        /// Conversion of the passphrase characters to bytes is performed using Convert.ToByte(), which is
+        /// the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
+        public PgpSecretKey(
+            int                         certificationLevel,
+            PgpKeyPair                  keyPair,
+            string                      id,
+            SymmetricKeyAlgorithmTag    encAlgorithm,
+            HashAlgorithmTag            hashAlgorithm,
+            char[]                      passPhrase,
+            bool                        useSha1,
+            PgpSignatureSubpacketVector hashedPackets,
+            PgpSignatureSubpacketVector unhashedPackets,
+            SecureRandom                rand)
+            : this(certificationLevel, keyPair, id, encAlgorithm, hashAlgorithm, false, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
         {
         }
 
+        /// <remarks>
+        /// If utf8PassPhrase is true, conversion of the passphrase to bytes uses Encoding.UTF8.GetBytes(), otherwise the conversion
+        /// is performed using Convert.ToByte(), which is the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
         public PgpSecretKey(
             int                         certificationLevel,
             PgpKeyPair                  keyPair,
             string                      id,
             SymmetricKeyAlgorithmTag    encAlgorithm,
             HashAlgorithmTag            hashAlgorithm,
+            bool                        utf8PassPhrase,
             char[]                      passPhrase,
             bool                        useSha1,
             PgpSignatureSubpacketVector hashedPackets,
             PgpSignatureSubpacketVector unhashedPackets,
             SecureRandom                rand)
-            : this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets, hashAlgorithm), encAlgorithm, passPhrase, useSha1, rand, true)
+            : this(certificationLevel, keyPair, id, encAlgorithm, hashAlgorithm,
+                PgpUtilities.EncodePassPhrase(passPhrase, utf8PassPhrase), true,
+                useSha1, hashedPackets, unhashedPackets, rand)
+        {
+        }
+
+        /// <remarks>
+        /// Allows the caller to handle the encoding of the passphrase to bytes.
+        /// </remarks>
+        public PgpSecretKey(
+            int                         certificationLevel,
+            PgpKeyPair                  keyPair,
+            string                      id,
+            SymmetricKeyAlgorithmTag    encAlgorithm,
+            HashAlgorithmTag            hashAlgorithm,
+            byte[]                      rawPassPhrase,
+            bool                        useSha1,
+            PgpSignatureSubpacketVector hashedPackets,
+            PgpSignatureSubpacketVector unhashedPackets,
+            SecureRandom                rand)
+            : this(certificationLevel, keyPair, id, encAlgorithm, hashAlgorithm, rawPassPhrase, false, useSha1, hashedPackets, unhashedPackets, rand)
+        {
+        }
+
+        internal PgpSecretKey(
+            int                         certificationLevel,
+            PgpKeyPair                  keyPair,
+            string                      id,
+            SymmetricKeyAlgorithmTag    encAlgorithm,
+            HashAlgorithmTag            hashAlgorithm,
+            byte[]                      rawPassPhrase,
+            bool                        clearPassPhrase,
+            bool                        useSha1,
+            PgpSignatureSubpacketVector hashedPackets,
+            PgpSignatureSubpacketVector unhashedPackets,
+            SecureRandom                rand)
+            : this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets, hashAlgorithm),
+                encAlgorithm, rawPassPhrase, clearPassPhrase, useSha1, rand, true)
         {
         }
 
@@ -269,7 +383,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             SecureRandom				rand)
             : this(certificationLevel,
                 new PgpKeyPair(algorithm, pubKey, privKey, time),
-                id, encAlgorithm, passPhrase, hashedPackets, unhashedPackets, rand)
+                id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand)
         {
         }
 
@@ -367,8 +481,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             get { return pub.GetUserAttributes(); }
         }
 
-        private byte[] ExtractKeyData(
-            char[] passPhrase)
+        private byte[] ExtractKeyData(byte[] rawPassPhrase, bool clearPassPhrase)
         {
             SymmetricKeyAlgorithmTag encAlgorithm = secret.EncAlgorithm;
             byte[] encData = secret.GetSecretKeyData();
@@ -380,7 +493,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             // TODO Factor this block out as 'decryptData'
             try
             {
-                KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, passPhrase);
+                KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, rawPassPhrase, clearPassPhrase);
                 byte[] iv = secret.GetIV();
                 byte[] data;
 
@@ -483,8 +596,34 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         }
 
         /// <summary>Extract a <c>PgpPrivateKey</c> from this secret key's encrypted contents.</summary>
-        public PgpPrivateKey ExtractPrivateKey(
-            char[] passPhrase)
+        /// <remarks>
+        /// Conversion of the passphrase characters to bytes is performed using Convert.ToByte(), which is
+        /// the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
+        public PgpPrivateKey ExtractPrivateKey(char[] passPhrase)
+        {
+            return DoExtractPrivateKey(PgpUtilities.EncodePassPhrase(passPhrase, false), true);
+        }
+
+        /// <summary>Extract a <c>PgpPrivateKey</c> from this secret key's encrypted contents.</summary>
+        /// <remarks>
+        /// The passphrase is encoded to bytes using UTF8 (Encoding.UTF8.GetBytes).
+        /// </remarks>
+        public PgpPrivateKey ExtractPrivateKeyUtf8(char[] passPhrase)
+        {
+            return DoExtractPrivateKey(PgpUtilities.EncodePassPhrase(passPhrase, true), true);
+        }
+
+        /// <summary>Extract a <c>PgpPrivateKey</c> from this secret key's encrypted contents.</summary>
+        /// <remarks>
+        /// Allows the caller to handle the encoding of the passphrase to bytes.
+        /// </remarks>
+        public PgpPrivateKey ExtractPrivateKeyRaw(byte[] rawPassPhrase)
+        {
+            return DoExtractPrivateKey(rawPassPhrase, false);
+        }
+
+        internal PgpPrivateKey DoExtractPrivateKey(byte[] rawPassPhrase, bool clearPassPhrase)
         {
             if (IsPrivateKeyEmpty)
                 return null;
@@ -492,7 +631,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             PublicKeyPacket pubPk = secret.PublicKeyPacket;
             try
             {
-                byte[] data = ExtractKeyData(passPhrase);
+                byte[] data = ExtractKeyData(rawPassPhrase, clearPassPhrase);
                 BcpgInputStream bcpgIn = BcpgInputStream.Wrap(new MemoryStream(data, false));
                 AsymmetricKeyParameter privateKey;
                 switch (pubPk.Algorithm)
@@ -652,6 +791,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         /// Return a copy of the passed in secret key, encrypted using a new password
         /// and the passed in algorithm.
         /// </summary>
+        /// <remarks>
+        /// Conversion of the passphrase characters to bytes is performed using Convert.ToByte(), which is
+        /// the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
         /// <param name="key">The PgpSecretKey to be copied.</param>
         /// <param name="oldPassPhrase">The current password for the key.</param>
         /// <param name="newPassPhrase">The new password for the key.</param>
@@ -664,11 +807,67 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             SymmetricKeyAlgorithmTag	newEncAlgorithm,
             SecureRandom				rand)
         {
+            return DoCopyWithNewPassword(key, PgpUtilities.EncodePassPhrase(oldPassPhrase, false),
+                PgpUtilities.EncodePassPhrase(newPassPhrase, false), true, newEncAlgorithm, rand);
+        }
+
+        /// <summary>
+        /// Return a copy of the passed in secret key, encrypted using a new password
+        /// and the passed in algorithm.
+        /// </summary>
+        /// <remarks>
+        /// The passphrase is encoded to bytes using UTF8 (Encoding.UTF8.GetBytes).
+        /// </remarks>
+        /// <param name="key">The PgpSecretKey to be copied.</param>
+        /// <param name="oldPassPhrase">The current password for the 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 PgpSecretKey CopyWithNewPasswordUtf8(
+            PgpSecretKey				key,
+            char[]						oldPassPhrase,
+            char[]						newPassPhrase,
+            SymmetricKeyAlgorithmTag	newEncAlgorithm,
+            SecureRandom				rand)
+        {
+            return DoCopyWithNewPassword(key, PgpUtilities.EncodePassPhrase(oldPassPhrase, true),
+                PgpUtilities.EncodePassPhrase(newPassPhrase, true), true, newEncAlgorithm, rand);
+        }
+
+        /// <summary>
+        /// Return a copy of the passed in secret key, encrypted using a new password
+        /// and the passed in algorithm.
+        /// </summary>
+        /// <remarks>
+        /// Allows the caller to handle the encoding of the passphrase to bytes.
+        /// </remarks>
+        /// <param name="key">The PgpSecretKey to be copied.</param>
+        /// <param name="rawOldPassPhrase">The current password for the key.</param>
+        /// <param name="rawNewPassPhrase">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 PgpSecretKey CopyWithNewPasswordRaw(
+            PgpSecretKey				key,
+            byte[]						rawOldPassPhrase,
+            byte[]						rawNewPassPhrase,
+            SymmetricKeyAlgorithmTag	newEncAlgorithm,
+            SecureRandom				rand)
+        {
+            return DoCopyWithNewPassword(key, rawOldPassPhrase, rawNewPassPhrase, false, newEncAlgorithm, rand);
+        }
 
+        internal static PgpSecretKey DoCopyWithNewPassword(
+            PgpSecretKey				key,
+            byte[]						rawOldPassPhrase,
+            byte[]						rawNewPassPhrase,
+            bool                        clearPassPhrase,
+            SymmetricKeyAlgorithmTag	newEncAlgorithm,
+            SecureRandom				rand)
+        {
             if (key.IsPrivateKeyEmpty)
                 throw new PgpException("no private key in this SecretKey - public key present only.");
 
-            byte[]	rawKeyData = key.ExtractKeyData(oldPassPhrase);
+            byte[]	rawKeyData = key.ExtractKeyData(rawOldPassPhrase, clearPassPhrase);
             int		s2kUsage = key.secret.S2kUsage;
             byte[]	iv = null;
             S2k		s2k = null;
@@ -696,11 +895,16 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             }
             else
             {
+                if (s2kUsage == SecretKeyPacket.UsageNone)
+                {
+                    s2kUsage = SecretKeyPacket.UsageChecksum;
+                }
+
                 try
                 {
                     if (pubKeyPacket.Version >= 4)
                     {
-                        keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2k, out iv);
+                        keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv);
                     }
                     else
                     {
@@ -749,7 +953,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         private static byte[] EncryptKeyData(
             byte[]						rawKeyData,
             SymmetricKeyAlgorithmTag	encAlgorithm,
-            char[]						passPhrase,
+            byte[]						rawPassPhrase,
+            bool                        clearPassPhrase,
             SecureRandom				random,
             out S2k						s2k,
             out byte[]					iv)
@@ -769,7 +974,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             random.NextBytes(s2kIV);
             s2k = new S2k(HashAlgorithmTag.Sha1, s2kIV, 0x60);
 
-            KeyParameter kp = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase);
+            KeyParameter kp = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase);
 
             iv = new byte[c.GetBlockSize()];
             random.NextBytes(iv);
@@ -779,13 +984,42 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             return c.DoFinal(rawKeyData);
         }
 
-        /**
-         * Parse a secret key from one of the GPG S expression keys associating it with the passed in public key.
-         *
-         * @return a secret key object.
-         */
+        /// <summary>
+        /// Parse a secret key from one of the GPG S expression keys associating it with the passed in public key.
+        /// </summary>
+        /// <remarks>
+        /// Conversion of the passphrase characters to bytes is performed using Convert.ToByte(), which is
+        /// the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
         public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] passPhrase, PgpPublicKey pubKey)
         {
+            return DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, false), true, pubKey);
+        }
+
+        /// <summary>
+        /// Parse a secret key from one of the GPG S expression keys associating it with the passed in public key.
+        /// </summary>
+        /// <remarks>
+        /// The passphrase is encoded to bytes using UTF8 (Encoding.UTF8.GetBytes).
+        /// </remarks>
+        public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[] passPhrase, PgpPublicKey pubKey)
+        {
+            return DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, true), true, pubKey);
+        }
+
+        /// <summary>
+        /// Parse a secret key from one of the GPG S expression keys associating it with the passed in public key.
+        /// </summary>
+        /// <remarks>
+        /// Allows the caller to handle the encoding of the passphrase to bytes.
+        /// </remarks>
+        public static PgpSecretKey ParseSecretKeyFromSExprRaw(Stream inputStream, byte[] rawPassPhrase, PgpPublicKey pubKey)
+        {
+            return DoParseSecretKeyFromSExpr(inputStream, rawPassPhrase, false, pubKey);
+        }
+
+        internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[] rawPassPhrase, bool clearPassPhrase, PgpPublicKey pubKey)
+        {
             SXprUtilities.SkipOpenParenthesis(inputStream);
 
             string type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
@@ -826,7 +1060,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
                 SXprUtilities.SkipCloseParenthesis(inputStream);
 
-                byte[] dValue = GetDValue(inputStream, passPhrase, curveName);
+                byte[] dValue = GetDValue(inputStream, rawPassPhrase, clearPassPhrase, curveName);
                 // TODO: check SHA-1 hash.
 
                 return new PgpSecretKey(new SecretKeyPacket(pubKey.PublicKeyPacket, SymmetricKeyAlgorithmTag.Null, null, null,
@@ -836,13 +1070,45 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             throw new PgpException("unknown key type found");
         }
 
-        /**
-        * Parse a secret key from one of the GPG S expression keys.
-        *
-        * @return a secret key object.
-        */
+        /// <summary>
+        /// Parse a secret key from one of the GPG S expression keys.
+        /// </summary>
+        /// <remarks>
+        /// Conversion of the passphrase characters to bytes is performed using Convert.ToByte(), which is
+        /// the historical behaviour of the library (1.7 and earlier).
+        /// </remarks>
         public static PgpSecretKey ParseSecretKeyFromSExpr(Stream inputStream, char[] passPhrase)
         {
+            return DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, false), true);
+        }
+
+        /// <summary>
+        /// Parse a secret key from one of the GPG S expression keys.
+        /// </summary>
+        /// <remarks>
+        /// The passphrase is encoded to bytes using UTF8 (Encoding.UTF8.GetBytes).
+        /// </remarks>
+        public static PgpSecretKey ParseSecretKeyFromSExprUtf8(Stream inputStream, char[] passPhrase)
+        {
+            return DoParseSecretKeyFromSExpr(inputStream, PgpUtilities.EncodePassPhrase(passPhrase, true), true);
+        }
+
+        /// <summary>
+        /// Parse a secret key from one of the GPG S expression keys.
+        /// </summary>
+        /// <remarks>
+        /// Allows the caller to handle the encoding of the passphrase to bytes.
+        /// </remarks>
+        public static PgpSecretKey ParseSecretKeyFromSExprRaw(Stream inputStream, byte[] rawPassPhrase)
+        {
+            return DoParseSecretKeyFromSExpr(inputStream, rawPassPhrase, false);
+        }
+
+        /// <summary>
+        /// Parse a secret key from one of the GPG S expression keys.
+        /// </summary>
+        internal static PgpSecretKey DoParseSecretKeyFromSExpr(Stream inputStream, byte[] rawPassPhrase, bool clearPassPhrase)
+        {
             SXprUtilities.SkipOpenParenthesis(inputStream);
 
             string type = SXprUtilities.ReadString(inputStream, inputStream.ReadByte());
@@ -891,7 +1157,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
                 SXprUtilities.SkipCloseParenthesis(inputStream);
 
-                byte[] dValue = GetDValue(inputStream, passPhrase, curveName);
+                byte[] dValue = GetDValue(inputStream, rawPassPhrase, clearPassPhrase, curveName);
                 // TODO: check SHA-1 hash.
 
                 return new PgpSecretKey(new SecretKeyPacket(pubPacket, SymmetricKeyAlgorithmTag.Null, null, null,
@@ -901,7 +1167,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             throw new PgpException("unknown key type found");
         }
 
-        private static byte[] GetDValue(Stream inputStream, char[] passPhrase, string curveName)
+        private static byte[] GetDValue(Stream inputStream, byte[] rawPassPhrase, bool clearPassPhrase, string curveName)
         {
             string type;
             SXprUtilities.SkipOpenParenthesis(inputStream);
@@ -932,7 +1198,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             }
 
             // TODO: recognise other algorithms
-            KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(SymmetricKeyAlgorithmTag.Aes128, s2k, passPhrase);
+            KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(SymmetricKeyAlgorithmTag.Aes128, s2k, rawPassPhrase, clearPassPhrase);
 
             byte[] data = RecoverKeyData(SymmetricKeyAlgorithmTag.Aes128, "/CBC/NoPadding", key, iv, secKeyData, 0, secKeyData.Length);