summary refs log tree commit diff
path: root/crypto/src/openpgp
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2015-10-18 20:53:15 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2015-10-18 20:53:15 +0700
commit0f9254b9238d5a36df1217bb354e9e76282067d7 (patch)
treea8d53d838c49ddc150b5d0ef2a79385fc3ba1d0f /crypto/src/openpgp
parentRemove the 'debug' logging from NaccacheStern (diff)
downloadBouncyCastle.NET-ed25519-0f9254b9238d5a36df1217bb354e9e76282067d7.tar.xz
http://www.bouncycastle.org/jira/browse/BMA-98
- Support v3 encryption
- Port more rewrap tests from Java API
Diffstat (limited to 'crypto/src/openpgp')
-rw-r--r--crypto/src/openpgp/PgpEncryptedDataGenerator.cs5
-rw-r--r--crypto/src/openpgp/PgpSecretKey.cs112
-rw-r--r--crypto/src/openpgp/PgpUtilities.cs13
3 files changed, 109 insertions, 21 deletions
diff --git a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
index 06868eab1..014281b24 100644
--- a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
+++ b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
@@ -311,10 +311,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
         internal void DoAddMethod(byte[] rawPassPhrase, bool clearPassPhrase, HashAlgorithmTag s2kDigest)
         {
-            byte[] iv = new byte[8];
-            rand.NextBytes(iv);
-
-            S2k s2k = new S2k(s2kDigest, iv, 0x60);
+            S2k s2k = PgpUtilities.GenerateS2k(s2kDigest, 0x60, rand);
 
             methods.Add(new PbeMethod(defAlgorithm, s2k, PgpUtilities.DoMakeKeyFromPassPhrase(defAlgorithm, s2k, rawPassPhrase, clearPassPhrase)));
         }
diff --git a/crypto/src/openpgp/PgpSecretKey.cs b/crypto/src/openpgp/PgpSecretKey.cs
index 0f472c1a4..d3811c44c 100644
--- a/crypto/src/openpgp/PgpSecretKey.cs
+++ b/crypto/src/openpgp/PgpSecretKey.cs
@@ -97,12 +97,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                     byte[] encData;
                     if (pub.Version >= 4)
                     {
-                        encData = EncryptKeyData(keyData, encAlgorithm, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv);
+                        encData = EncryptKeyDataV4(keyData, encAlgorithm, HashAlgorithmTag.Sha1, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv);
                     }
                     else
                     {
-                        // TODO v3 RSA key encryption
-                        throw Platform.CreateNotImplementedException("v3 RSA");
+                        encData = EncryptKeyDataV3(keyData, encAlgorithm, rawPassPhrase, clearPassPhrase, rand, out s2k, out iv);
                     }
 
                     int s2kUsage = useSha1
@@ -461,6 +460,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             get { return pub.KeyId; }
         }
 
+        /// <summary>Return the S2K usage associated with this key.</summary>
+        public int S2kUsage
+        {
+            get { return secret.S2kUsage; }
+        }
+
+        /// <summary>Return the S2K used to process this key.</summary>
+        public S2k S2k
+        {
+            get { return secret.S2k; }
+        }
+
         /// <summary>The public key associated with this key.</summary>
         public PgpPublicKey PublicKey
         {
@@ -904,12 +915,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 {
                     if (pubKeyPacket.Version >= 4)
                     {
-                        keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv);
+                        keyData = EncryptKeyDataV4(rawKeyData, newEncAlgorithm, HashAlgorithmTag.Sha1, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv);
                     }
                     else
                     {
-                        // TODO v3 RSA key encryption
-                        throw Platform.CreateNotImplementedException("v3 RSA");
+                        keyData = EncryptKeyDataV3(rawKeyData, newEncAlgorithm, rawNewPassPhrase, clearPassPhrase, rand, out s2k, out iv);
                     }
                 }
                 catch (PgpException e)
@@ -950,7 +960,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             return new PgpSecretKey(secretKey.secret, publicKey);
         }
 
-        private static byte[] EncryptKeyData(
+        private static byte[] EncryptKeyDataV3(
             byte[]						rawKeyData,
             SymmetricKeyAlgorithmTag	encAlgorithm,
             byte[]						rawPassPhrase,
@@ -959,6 +969,78 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             out S2k						s2k,
             out byte[]					iv)
         {
+            // Version 2 or 3 - RSA Keys only
+
+            s2k = null;
+            iv = null;
+
+            KeyParameter encKey = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase);
+
+            byte[] keyData = new byte[rawKeyData.Length];
+
+            //
+            // process 4 numbers
+            //
+            int pos = 0;
+            for (int i = 0; i != 4; i++)
+            {
+                int encLen = (((rawKeyData[pos] << 8) | (rawKeyData[pos + 1] & 0xff)) + 7) / 8;
+
+                keyData[pos] = rawKeyData[pos];
+                keyData[pos + 1] = rawKeyData[pos + 1];
+
+                byte[] tmp;
+                if (i == 0)
+                {
+                    tmp = EncryptData(encAlgorithm, encKey, rawKeyData, pos + 2, encLen, random, ref iv);
+                }
+                else
+                {
+                    byte[] tmpIv = Arrays.CopyOfRange(keyData, pos - iv.Length, pos);
+
+                    tmp = EncryptData(encAlgorithm, encKey, rawKeyData, pos + 2, encLen, random, ref tmpIv);
+                }
+
+                Array.Copy(tmp, 0, keyData, pos + 2, tmp.Length);
+                pos += 2 + encLen;
+            }
+
+            //
+            // copy in checksum.
+            //
+            keyData[pos] = rawKeyData[pos];
+            keyData[pos + 1] = rawKeyData[pos + 1];
+
+            return keyData;
+        }
+
+        private static byte[] EncryptKeyDataV4(
+            byte[]						rawKeyData,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            HashAlgorithmTag            hashAlgorithm,
+            byte[]						rawPassPhrase,
+            bool                        clearPassPhrase,
+            SecureRandom				random,
+            out S2k						s2k,
+            out byte[]					iv)
+        {
+            s2k = PgpUtilities.GenerateS2k(hashAlgorithm, 0x60, random);
+
+            KeyParameter key = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase);
+
+            iv = null;
+            return EncryptData(encAlgorithm, key, rawKeyData, 0, rawKeyData.Length, random, ref iv);
+        }
+
+        private static byte[] EncryptData(
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            KeyParameter                key,
+            byte[]						data,
+            int                         dataOff,
+            int                         dataLen,
+            SecureRandom				random,
+            ref byte[]                  iv)
+        {
             IBufferedCipher c;
             try
             {
@@ -970,18 +1052,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 throw new PgpException("Exception creating cipher", e);
             }
 
-            byte[] s2kIV = new byte[8];
-            random.NextBytes(s2kIV);
-            s2k = new S2k(HashAlgorithmTag.Sha1, s2kIV, 0x60);
-
-            KeyParameter kp = PgpUtilities.DoMakeKeyFromPassPhrase(encAlgorithm, s2k, rawPassPhrase, clearPassPhrase);
-
-            iv = new byte[c.GetBlockSize()];
-            random.NextBytes(iv);
+            if (iv == null)
+            {
+                iv = PgpUtilities.GenerateIV(c.GetBlockSize(), random);
+            }
 
-            c.Init(true, new ParametersWithRandom(new ParametersWithIV(kp, iv), random));
+            c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), random));
 
-            return c.DoFinal(rawKeyData);
+            return c.DoFinal(data, dataOff, dataLen);
         }
 
         /// <summary>
diff --git a/crypto/src/openpgp/PgpUtilities.cs b/crypto/src/openpgp/PgpUtilities.cs
index 65c07b2e2..4f3cb6e73 100644
--- a/crypto/src/openpgp/PgpUtilities.cs
+++ b/crypto/src/openpgp/PgpUtilities.cs
@@ -488,5 +488,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 throw new PgpException("unknown wrap algorithm: " + encAlgorithm);
             }
         }
+
+        internal static byte[] GenerateIV(int length, SecureRandom random)
+        {
+            byte[] iv = new byte[length];
+            random.NextBytes(iv);
+            return iv;
+        }
+
+        internal static S2k GenerateS2k(HashAlgorithmTag hashAlgorithm, int s2kCount, SecureRandom random)
+        {
+            byte[] iv = GenerateIV(8, random);
+            return new S2k(hashAlgorithm, iv, s2kCount);
+        }
     }
 }