summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/openpgp/PgpEncryptedDataGenerator.cs20
-rw-r--r--crypto/src/openpgp/PgpPad.cs46
-rw-r--r--crypto/src/openpgp/PgpPublicKey.cs16
-rw-r--r--crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs2
4 files changed, 60 insertions, 24 deletions
diff --git a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
index 014281b24..336baf00d 100644
--- a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
+++ b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs
@@ -82,11 +82,13 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             : EncMethod
         {
 			internal PgpPublicKey pubKey;
+            internal bool sessionKeyObfuscation;
             internal byte[][] data;
 
-            internal PubMethod(PgpPublicKey pubKey)
+            internal PubMethod(PgpPublicKey pubKey, bool sessionKeyObfuscation)
             {
                 this.pubKey = pubKey;
+                this.sessionKeyObfuscation = sessionKeyObfuscation;
             }
 
             public override void AddSessionInfo(
@@ -144,7 +146,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 IWrapper w = PgpUtilities.CreateWrapper(ecKey.SymmetricKeyAlgorithm);
                 w.Init(true, new ParametersWithRandom(key, random));
 
-                byte[] paddedSessionData = PgpPad.PadSessionData(sessionInfo);
+                byte[] paddedSessionData = PgpPad.PadSessionData(sessionInfo, sessionKeyObfuscation);
 
                 byte[] C = w.Wrap(paddedSessionData, 0, paddedSessionData.Length);
                 byte[] VB = new MPInteger(new BigInteger(1, ephPub.Q.GetEncoded(false))).GetEncoded();
@@ -317,18 +319,22 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         }
 
         /// <summary>Add a public key encrypted session key to the encrypted object.</summary>
-        public void AddMethod(
-            PgpPublicKey key)
+        public void AddMethod(PgpPublicKey key)
         {
-			if (!key.IsEncryptionKey)
+            AddMethod(key, true);
+        }
+
+        public void AddMethod(PgpPublicKey key, bool sessionKeyObfuscation)
+        {
+            if (!key.IsEncryptionKey)
             {
                 throw new ArgumentException("passed in key not an encryption key!");
             }
 
-			methods.Add(new PubMethod(key));
+            methods.Add(new PubMethod(key, sessionKeyObfuscation));
         }
 
-		private void AddCheckSum(
+        private void AddCheckSum(
             byte[] sessionInfo)
         {
 			Debug.Assert(sessionInfo != null);
diff --git a/crypto/src/openpgp/PgpPad.cs b/crypto/src/openpgp/PgpPad.cs
index 48f7f2f44..227e31019 100644
--- a/crypto/src/openpgp/PgpPad.cs
+++ b/crypto/src/openpgp/PgpPad.cs
@@ -11,35 +11,55 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
         public static byte[] PadSessionData(byte[] sessionInfo)
         {
-            byte[] result = new byte[40];
-
-            Array.Copy(sessionInfo, 0, result, 0, sessionInfo.Length);
+            return PadSessionData(sessionInfo, true);
+        }
 
-            byte padValue = (byte)(result.Length - sessionInfo.Length);
+        public static byte[] PadSessionData(byte[] sessionInfo, bool obfuscate)
+        {
+            int length = sessionInfo.Length;
+            int paddedLength = ((length >> 3) + 1) << 3;
 
-            for (int i = sessionInfo.Length; i != result.Length; i++)
+            if (obfuscate)
             {
-                result[i] = padValue;
+                paddedLength = System.Math.Max(40, paddedLength);
             }
 
+            int padCount = paddedLength - length;
+            byte padByte = (byte)padCount;
+
+            byte[] result = new byte[paddedLength];
+            Array.Copy(sessionInfo, 0, result, 0, length);
+            for (int i = length; i < paddedLength; ++i)
+            {
+                result[i] = padByte;
+            }
             return result;
         }
 
         public static byte[] UnpadSessionData(byte[] encoded)
         {
-            byte padValue = encoded[encoded.Length - 1];
+            int paddedLength = encoded.Length;
+            byte padByte = encoded[paddedLength - 1];
+            int padCount = padByte;
+            int length = paddedLength - padCount;
+            int last = length - 1;
 
-            for (int i = encoded.Length - padValue; i != encoded.Length; i++)
+            int diff = 0;
+            for (int i = 0; i < paddedLength; ++i)
             {
-                if (encoded[i] != padValue)
-                    throw new PgpException("bad padding found in session data");
+                int mask = (last - i) >> 31;
+                diff |= (padByte ^ encoded[i]) & mask;
             }
 
-            byte[] taggedKey = new byte[encoded.Length - padValue];
+            diff |= paddedLength & 7;
+            diff |= (40 - paddedLength) >> 31;
 
-            Array.Copy(encoded, 0, taggedKey, 0, taggedKey.Length);
+            if (diff != 0)
+                throw new PgpException("bad padding found in session data");
 
-            return taggedKey;
+            byte[] result = new byte[length];
+            Array.Copy(encoded, 0, result, 0, length);
+            return result;
         }
     }
 }
diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs
index fc125e8c8..92422c413 100644
--- a/crypto/src/openpgp/PgpPublicKey.cs
+++ b/crypto/src/openpgp/PgpPublicKey.cs
@@ -72,7 +72,8 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             PgpSignature.PositiveCertification,
             PgpSignature.CasualCertification,
             PgpSignature.NoCertification,
-            PgpSignature.DefaultCertification
+            PgpSignature.DefaultCertification,
+            PgpSignature.DirectKey,
         };
 
         private long				keyId;
@@ -369,6 +370,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 {
                     return seconds;
                 }
+
+                seconds = GetExpirationTimeFromSig(false, PgpSignature.DirectKey);
+                if (seconds >= 0)
+                {
+                    return seconds;
+                }
             }
 
             return 0;
@@ -388,6 +395,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 if (hashed == null)
                     continue;
 
+                if (!hashed.HasSubpacket(SignatureSubpacketTag.KeyExpireTime))
+                    continue;
+
                 long current = hashed.GetKeyExpirationTime();
 
                 if (sig.KeyId == this.KeyId)
@@ -447,10 +457,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             }
         }
 
-        /// <summary>True, if this is a master key.</summary>
+        /// <summary>True, if this could be a master key.</summary>
         public bool IsMasterKey
         {
-            get { return subSigs == null; }
+            get { return (subSigs == null) && !(this.IsEncryptionKey && publicPk.Algorithm != PublicKeyAlgorithmTag.RsaGeneral); }
         }
 
         /// <summary>The algorithm code associated with the public key.</summary>
diff --git a/crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs b/crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs
index 8e4f7a3b5..6a12f9059 100644
--- a/crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs
+++ b/crypto/test/src/openpgp/examples/ClearSignedFileProcessor.cs
@@ -14,7 +14,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
     * To sign a file: ClearSignedFileProcessor -s fileName secretKey passPhrase.
 	* </p>
     * <p>
-    * To decrypt: ClearSignedFileProcessor -v fileName signatureFile publicKeyFile.
+    * To decrypt: ClearSignedFileProcessor -v signatureFile publicKeyFile.
 	* </p>
     */
     public sealed class ClearSignedFileProcessor