Remove CKey, add signature verification support to CPubKey plus some tests
[NovacoinLibrary.git] / Novacoin / CKeyPair.cs
1 \feffusing System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 using Org.BouncyCastle.Math;
8 using Org.BouncyCastle.Math.EC;
9
10 using Org.BouncyCastle.Crypto;
11 using Org.BouncyCastle.Crypto.Generators;
12 using Org.BouncyCastle.Crypto.Parameters;
13
14 using Org.BouncyCastle.Asn1.X9;
15 using Org.BouncyCastle.Security;
16 using Org.BouncyCastle.Asn1.Sec;
17
18 namespace Novacoin
19 {
20     public class CKeyPair
21     {
22         private BigInteger D;
23         private ECPoint Q;
24
25         private static X9ECParameters curve = SecNamedCurves.GetByName("secp256k1");
26         private static ECDomainParameters domain = new ECDomainParameters(curve.Curve, curve.G, curve.N, curve.H, curve.GetSeed());
27
28         /// <summary>
29         /// Initialize new CKeyPair instance with random secret.
30         /// </summary>
31         public CKeyPair()
32         {
33             ECKeyGenerationParameters genParams = new ECKeyGenerationParameters(domain, new SecureRandom());
34
35             ECKeyPairGenerator generator = new ECKeyPairGenerator("ECDSA");
36             generator.Init(genParams);
37             AsymmetricCipherKeyPair ecKeyPair = generator.GenerateKeyPair();
38
39             Q = ((ECPublicKeyParameters)ecKeyPair.Public).Q;
40             D = ((ECPrivateKeyParameters)ecKeyPair.Private).D;
41         }
42
43         /// <summary>
44         /// Init key pair using secret sequence of bytes
45         /// </summary>
46         /// <param name="secretBytes">Byte sequence</param>
47         public CKeyPair(IEnumerable<byte> secretBytes)
48         {
49             D = new BigInteger(secretBytes.ToArray());
50             Q = curve.G.Multiply(D);
51         }
52
53         /// <summary>
54         /// Create signature for supplied data
55         /// </summary>
56         /// <param name="data">Data bytes sequence</param>
57         /// <returns>Signature bytes sequence</returns>
58         public IEnumerable<byte> Sign(IEnumerable<byte> data)
59         {
60             byte[] dataBytes = data.ToArray();
61
62             ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA");
63             ECPrivateKeyParameters keyParameters = new ECPrivateKeyParameters(D, domain);
64             signer.Init(true, keyParameters);
65             signer.BlockUpdate(dataBytes, 0, dataBytes.Length);
66
67             return signer.GenerateSignature();
68         }
69
70         public bool Verify(IEnumerable<byte> data, IEnumerable<byte> signature)
71         {
72             byte[] dataBytes = data.ToArray();
73
74             ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA");
75             ECPublicKeyParameters keyParameters = new ECPublicKeyParameters(Q, domain);
76             signer.Init(false, keyParameters);
77             signer.BlockUpdate(dataBytes, 0, dataBytes.Length);
78
79             return signer.VerifySignature(signature.ToArray());
80         }
81
82         public CPubKey GetPubKey()
83         {
84             return new CPubKey(Q);
85         }
86
87         /// <summary>
88         /// Calculate Hash160 and create new CKeyID instance.
89         /// </summary>
90         /// <returns>New key ID</returns>
91         public CKeyID GetKeyID()
92         {
93             return new CKeyID(Hash160.Compute160(Public));
94         }
95
96         /// <summary>
97         /// Secret part of key pair
98         /// </summary>
99         public IEnumerable<byte> Secret
100         {
101             get { return D.ToByteArray(); }
102         }
103
104         /// <summary>
105         /// Public part of key pair
106         /// </summary>
107         public IEnumerable<byte> Public
108         {
109             get { return Q.GetEncoded(); }
110         }
111
112         public override string ToString()
113         {
114             StringBuilder sb = new StringBuilder();
115
116             sb.AppendFormat("CKeyPair(Secret={0}, Public={1})", Interop.ToHex(Secret), Interop.ToHex(Public));
117
118             return sb.ToString();
119         }
120     }
121 }