Comments
[NovacoinLibrary.git] / Novacoin / CKeyPair.cs
1 \feff/**
2  *  Novacoin classes library
3  *  Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
4
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 using Org.BouncyCastle.Crypto;
20 using Org.BouncyCastle.Crypto.Generators;
21 using Org.BouncyCastle.Crypto.Parameters;
22 using Org.BouncyCastle.Math;
23 using Org.BouncyCastle.Security;
24 using System.Collections.Generic;
25 using System.Linq;
26
27
28 namespace Novacoin
29 {
30     public class CKeyPair : CKey
31     {
32         private ECPrivateKeyParameters _Private;
33
34         /// <summary>
35         /// Initialize new CKeyPair instance with random secret.
36         /// </summary>
37         public CKeyPair(bool Compressed=true)
38         {
39             var genParams = new ECKeyGenerationParameters(domain, new SecureRandom());
40             var generator = new ECKeyPairGenerator("ECDSA");
41             generator.Init(genParams);
42             var ecKeyPair = generator.GenerateKeyPair();
43
44             _Private = (ECPrivateKeyParameters)ecKeyPair.Private;
45             _Public = (ECPublicKeyParameters)ecKeyPair.Public;
46
47             if (Compressed)
48             {
49                 _Public = Compress(_Public);
50             }
51         }
52
53         /// <summary>
54         /// Init key pair using secret sequence of bytes
55         /// </summary>
56         /// <param name="secretBytes">Byte sequence</param>
57         /// <param name="Compressed">Compression flag</param>
58         public CKeyPair(byte[] secretBytes, bool Compressed=true)
59         {
60             // Deserialize secret value
61             var D = new BigInteger(secretBytes.Take(32).ToArray());
62
63             if (D.SignValue == -1)
64             {
65                 var fixedKeyBytes = secretBytes.Take(32).ToList();
66                 fixedKeyBytes.Insert(0, 0x00); // prepend with sign byte
67
68                 D = new BigInteger(fixedKeyBytes.ToArray());
69             }
70
71             // Calculate public key
72             var Q = curve.G.Multiply(D);
73
74             _Private = new ECPrivateKeyParameters(D, domain);
75             _Public = new ECPublicKeyParameters(Q, domain);
76
77             if (Compressed)
78             {
79                 _Public = Compress(_Public);
80             }
81         }
82
83         /// <summary>
84         /// Init key pair using secret sequence of bytes
85         /// </summary>
86         /// <param name="secretBytes">Byte sequence</param>
87         public CKeyPair(byte[] secretBytes) : 
88             this (secretBytes.Take(32).ToArray(), (secretBytes.Count() == 33 && secretBytes.Last() == 0x01))
89         {
90         }
91
92         public CKeyPair(string strBase58)
93         {
94             var rawBytes = AddressTools.Base58DecodeCheck(strBase58).ToList();
95             rawBytes.RemoveAt(0); // Remove key version byte
96
97             // Deserialize secret value
98             var D = new BigInteger(rawBytes.Take(32).ToArray());
99
100             if (D.SignValue == -1)
101             {
102                 var secretbytes = rawBytes.Take(32).ToList(); // Copy secret
103                 secretbytes.Insert(0, 0x00); // Prepend with sign byte
104
105                 D = new BigInteger(secretbytes.ToArray()); // Try decoding again
106             }
107
108             // Calculate public key
109             var Q = curve.G.Multiply(D);
110
111             _Private = new ECPrivateKeyParameters(D, domain);
112             _Public = new ECPublicKeyParameters(Q, domain);
113
114             if (rawBytes.Count == 33 && rawBytes.Last() == 0x01) // Check compression tag
115             {
116                 _Public = Compress(_Public);
117             }
118         }
119
120         /// <summary>
121         /// Initialize a copy of CKeyPair instance
122         /// </summary>
123         /// <param name="pair">CKyPair instance</param>
124         public CKeyPair(CKeyPair pair)
125         {
126             _Public = pair._Public;
127             _Private = pair._Private;
128         }
129
130         /// <summary>
131         /// Create signature for supplied data
132         /// </summary>
133         /// <param name="data">Hash to sigh</param>
134         /// <returns>Signature bytes sequence</returns>
135         public byte[] Sign(Hash sigHash)
136         {
137             var signer = SignerUtilities.GetSigner("NONEwithECDSA");
138             signer.Init(true, _Private);
139             signer.BlockUpdate(sigHash.hashBytes, 0, sigHash.hashSize);
140
141             return signer.GenerateSignature();
142         }
143
144         public CPubKey PubKey
145         {
146             get { return new CPubKey(PublicBytes); }
147         }
148
149         /// <summary>
150         /// SecretBytes part of key pair
151         /// </summary>
152         public byte[] SecretBytes
153         {
154             get
155             {
156                 var secretBytes = new List<byte>(_Private.D.ToByteArray());
157
158                 if (secretBytes[0] == 0x00)
159                 {
160                     // Remove sign
161                     secretBytes.RemoveAt(0);
162                 }
163
164                 if (IsCompressed)
165                 {
166                     // Set compression flag
167                     secretBytes.Add(0x01);
168                 }
169
170                 return secretBytes.ToArray();
171             }
172         }
173
174         public string ToHex()
175         {
176             return Interop.ToHex(SecretBytes);
177         }
178
179         public override string ToString()
180         {
181             var r = new List<byte>();
182
183             r.Add((byte)(128 + AddrType.PUBKEY_ADDRESS)); // Key version
184             r.AddRange(SecretBytes); // Key data
185
186             return AddressTools.Base58EncodeCheck(r.ToArray());
187         }
188     }
189 }