summary refs log tree commit diff
path: root/crypto/src/openpgp/PgpPublicKey.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/openpgp/PgpPublicKey.cs')
-rw-r--r--crypto/src/openpgp/PgpPublicKey.cs132
1 files changed, 92 insertions, 40 deletions
diff --git a/crypto/src/openpgp/PgpPublicKey.cs b/crypto/src/openpgp/PgpPublicKey.cs
index 5bde2c8fe..904e29913 100644
--- a/crypto/src/openpgp/PgpPublicKey.cs
+++ b/crypto/src/openpgp/PgpPublicKey.cs
@@ -2,10 +2,14 @@ using System;
 using System.Collections;
 using System.IO;
 
+using Org.BouncyCastle.Asn1.Sec;
 using Org.BouncyCastle.Asn1.X9;
 using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
 using Org.BouncyCastle.Crypto.IO;
 using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
 using Org.BouncyCastle.Security;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
@@ -15,6 +19,54 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
     /// <remarks>General class to handle a PGP public key object.</remarks>
     public class PgpPublicKey
     {
+        public static byte[] CalculateFingerprint(PublicKeyPacket publicPk)
+        {
+            IBcpgKey key = publicPk.Key;
+            IDigest digest;
+
+            if (publicPk.Version <= 3)
+            {
+                RsaPublicBcpgKey rK = (RsaPublicBcpgKey)key;
+
+                try
+                {
+                    digest = DigestUtilities.GetDigest("MD5");
+                    UpdateDigest(digest, rK.Modulus);
+                    UpdateDigest(digest, rK.PublicExponent);
+                }
+                catch (Exception e)
+                {
+                    throw new PgpException("can't encode key components: " + e.Message, e);
+                }
+            }
+            else
+            {
+                try
+                {
+                    byte[] kBytes = publicPk.GetEncodedContents();
+
+                    digest = DigestUtilities.GetDigest("SHA1");
+
+                    digest.Update(0x99);
+                    digest.Update((byte)(kBytes.Length >> 8));
+                    digest.Update((byte)kBytes.Length);
+                    digest.BlockUpdate(kBytes, 0, kBytes.Length);
+                }
+                catch (Exception e)
+                {
+                    throw new PgpException("can't encode key components: " + e.Message, e);
+                }
+            }
+
+            return DigestUtilities.DoFinal(digest);
+        }
+
+        private static void UpdateDigest(IDigest d, BigInteger b)
+        {
+            byte[] bytes = b.ToByteArrayUnsigned();
+            d.BlockUpdate(bytes, 0, bytes.Length);
+        }
+
         private static readonly int[] MasterKeyCertificationTypes = new int[]
         {
             PgpSignature.PositiveCertification,
@@ -39,51 +91,17 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
         {
             IBcpgKey key = publicPk.Key;
 
+            this.fingerprint = CalculateFingerprint(publicPk);
+
             if (publicPk.Version <= 3)
             {
                 RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key;
 
                 this.keyId = rK.Modulus.LongValue;
-
-                try
-                {
-                    IDigest digest = DigestUtilities.GetDigest("MD5");
-
-                    byte[] bytes = rK.Modulus.ToByteArrayUnsigned();
-                    digest.BlockUpdate(bytes, 0, bytes.Length);
-
-                    bytes = rK.PublicExponent.ToByteArrayUnsigned();
-                    digest.BlockUpdate(bytes, 0, bytes.Length);
-
-                    this.fingerprint = DigestUtilities.DoFinal(digest);
-                }
-                //catch (NoSuchAlgorithmException)
-                catch (Exception e)
-                {
-                    throw new IOException("can't find MD5", e);
-                }
-
                 this.keyStrength = rK.Modulus.BitLength;
             }
             else
             {
-                byte[] kBytes = publicPk.GetEncodedContents();
-
-                try
-                {
-                    IDigest digest = DigestUtilities.GetDigest("SHA1");
-
-                    digest.Update(0x99);
-                    digest.Update((byte)(kBytes.Length >> 8));
-                    digest.Update((byte)kBytes.Length);
-                    digest.BlockUpdate(kBytes, 0, kBytes.Length);
-                    this.fingerprint = DigestUtilities.DoFinal(digest);
-                }
-                catch (Exception e)
-                {
-                    throw new IOException("can't find SHA1", e);
-                }
-
                 this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56)
                     | ((ulong)fingerprint[fingerprint.Length - 7] << 48)
                     | ((ulong)fingerprint[fingerprint.Length - 6] << 40)
@@ -107,7 +125,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                 }
                 else if (key is ECPublicBcpgKey)
                 {
-                    this.keyStrength = ECNamedCurveTable.GetByOid(((ECPublicBcpgKey)key).CurveOid).Curve.FieldSize;
+                    this.keyStrength = ECKeyPairGenerator.FindECCurveByOid(((ECPublicBcpgKey)key).CurveOid).Curve.FieldSize;
                 }
             }
         }
@@ -146,6 +164,23 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
 
                 bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y);
             }
+            else if (pubKey is ECPublicKeyParameters)
+            {
+                ECPublicKeyParameters ecK = (ECPublicKeyParameters)pubKey;
+
+                if (algorithm == PublicKeyAlgorithmTag.ECDH)
+                {
+                    bcpgKey = new ECDHPublicBcpgKey(ecK.PublicKeyParamSet, ecK.Q, HashAlgorithmTag.Sha256, SymmetricKeyAlgorithmTag.Aes128);
+                }
+                else if (algorithm == PublicKeyAlgorithmTag.ECDsa)
+                {
+                    bcpgKey = new ECDsaPublicBcpgKey(ecK.PublicKeyParamSet, ecK.Q);
+                }
+                else
+                {
+                    throw new PgpException("unknown EC algorithm");
+                }
+            }
             else if (pubKey is ElGamalPublicKeyParameters)
             {
                 ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey;
@@ -172,6 +207,11 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             }
         }
 
+        public PgpPublicKey(PublicKeyPacket publicPk)
+            : this(publicPk, Platform.CreateArrayList(), Platform.CreateArrayList())
+        {
+        }
+
         /// <summary>Constructor for a sub-key.</summary>
         internal PgpPublicKey(
             PublicKeyPacket	publicPk,
@@ -426,14 +466,18 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
                     case PublicKeyAlgorithmTag.RsaEncrypt:
                     case PublicKeyAlgorithmTag.RsaGeneral:
                     case PublicKeyAlgorithmTag.RsaSign:
-                        RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey) publicPk.Key;
+                        RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey)publicPk.Key;
                         return new RsaKeyParameters(false, rsaK.Modulus, rsaK.PublicExponent);
                     case PublicKeyAlgorithmTag.Dsa:
-                        DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey) publicPk.Key;
+                        DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey)publicPk.Key;
                         return new DsaPublicKeyParameters(dsaK.Y, new DsaParameters(dsaK.P, dsaK.Q, dsaK.G));
+                    case PublicKeyAlgorithmTag.ECDsa:
+                        return GetECKey("ECDSA");
+                    case PublicKeyAlgorithmTag.ECDH:
+                        return GetECKey("ECDH");
                     case PublicKeyAlgorithmTag.ElGamalEncrypt:
                     case PublicKeyAlgorithmTag.ElGamalGeneral:
-                        ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey) publicPk.Key;
+                        ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey)publicPk.Key;
                         return new ElGamalPublicKeyParameters(elK.Y, new ElGamalParameters(elK.P, elK.G));
                     default:
                         throw new PgpException("unknown public key algorithm encountered");
@@ -449,6 +493,14 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
             }
         }
 
+        private ECPublicKeyParameters GetECKey(string algorithm)
+        {
+            ECPublicBcpgKey ecK = (ECPublicBcpgKey)publicPk.Key;
+            X9ECParameters x9 = ECKeyPairGenerator.FindECCurveByOid(ecK.CurveOid);
+            ECPoint q = x9.Curve.DecodePoint(BigIntegers.AsUnsignedByteArray(ecK.EncodedPoint));
+            return new ECPublicKeyParameters(algorithm, q, ecK.CurveOid);
+        }
+
         /// <summary>Allows enumeration of any user IDs associated with the key.</summary>
         /// <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
         public IEnumerable GetUserIds()