Alternate privkey generation method, disabled for now
[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
22 using System.Security.Cryptography;
23
24 using Org.BouncyCastle.Crypto.Parameters;
25 using Org.BouncyCastle.Math;
26 using Org.BouncyCastle.Security;
27 using System.Collections.Generic;
28 using System.Linq;
29
30
31 namespace Novacoin
32 {
33     public class CKeyPair : CKey
34     {
35         private ECPrivateKeyParameters _Private;
36         private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
37
38         /// <summary>
39         /// Initialize new CKeyPair instance with random secret.
40         /// </summary>
41         public CKeyPair(bool Compressed = true)
42         {
43
44
45             var genParams = new ECKeyGenerationParameters(domain, new SecureRandom());
46             var generator = new ECKeyPairGenerator("ECDSA");
47             generator.Init(genParams);
48             var ecKeyPair = generator.GenerateKeyPair();
49
50             _Private = (ECPrivateKeyParameters)ecKeyPair.Private;
51             _Public = (ECPublicKeyParameters)ecKeyPair.Public;
52
53             /*
54               BigInteger D;
55               var buffer1 = new byte[32];
56               var buffer2 = new byte[32];
57
58               do
59               {
60                   rng.GetBytes(buffer1);
61                   rng.GetNonZeroBytes(buffer2);
62
63                   D = new BigInteger(Hash256.ComputeRaw256(ref buffer1, ref buffer2));
64
65                   if (D.BitLength < 249)
66                       System.Console.WriteLine(D.BitLength);
67               }
68               while (D.SignValue == -1);
69
70               var Q = curve.G.Multiply(D);
71
72               _Private = new ECPrivateKeyParameters(D, domain);
73               _Public = new ECPublicKeyParameters(Q, domain);
74             */
75
76             if (Compressed)
77             {
78                 _Public = Compress(_Public);
79             }
80         }
81
82         /// <summary>
83         /// Init key pair using secret sequence of bytes
84         /// </summary>
85         /// <param name="secretBytes">Byte sequence</param>
86         /// <param name="Compressed">Compression flag</param>
87         public CKeyPair(byte[] secretBytes, bool Compressed=true)
88         {
89             // Deserialize secret value
90             var D = new BigInteger(secretBytes.Take(32).ToArray());
91
92             if (D.SignValue == -1)
93             {
94                 var fixedKeyBytes = secretBytes.Take(32).ToList();
95                 fixedKeyBytes.Insert(0, 0x00); // prepend with sign byte
96
97                 D = new BigInteger(fixedKeyBytes.ToArray());
98             }
99
100             // Calculate public key
101             var Q = curve.G.Multiply(D);
102
103             _Private = new ECPrivateKeyParameters(D, domain);
104             _Public = new ECPublicKeyParameters(Q, domain);
105
106             if (Compressed)
107             {
108                 _Public = Compress(_Public);
109             }
110         }
111
112         /// <summary>
113         /// Init key pair using secret sequence of bytes
114         /// </summary>
115         /// <param name="secretBytes">Byte sequence</param>
116         public CKeyPair(byte[] secretBytes) : 
117             this (secretBytes.Take(32).ToArray(), (secretBytes.Count() == 33 && secretBytes.Last() == 0x01))
118         {
119         }
120
121         public CKeyPair(string strBase58)
122         {
123             var rawBytes = AddressTools.Base58DecodeCheck(strBase58).ToList();
124             rawBytes.RemoveAt(0); // Remove key version byte
125
126             // Deserialize secret value
127             var D = new BigInteger(rawBytes.Take(32).ToArray());
128
129             if (D.SignValue == -1)
130             {
131                 var secretbytes = rawBytes.Take(32).ToList(); // Copy secret
132                 secretbytes.Insert(0, 0x00); // Prepend with sign byte
133
134                 D = new BigInteger(secretbytes.ToArray()); // Try decoding again
135             }
136
137             // Calculate public key
138             var Q = curve.G.Multiply(D);
139
140             _Private = new ECPrivateKeyParameters(D, domain);
141             _Public = new ECPublicKeyParameters(Q, domain);
142
143             if (rawBytes.Count == 33 && rawBytes.Last() == 0x01) // Check compression tag
144             {
145                 _Public = Compress(_Public);
146             }
147         }
148
149         /// <summary>
150         /// Initialize a copy of CKeyPair instance
151         /// </summary>
152         /// <param name="pair">CKyPair instance</param>
153         public CKeyPair(CKeyPair pair)
154         {
155             _Public = pair._Public;
156             _Private = pair._Private;
157         }
158
159         /// <summary>
160         /// Create signature for supplied data
161         /// </summary>
162         /// <param name="data">Hash to sigh</param>
163         /// <returns>Signature bytes sequence</returns>
164         public byte[] Sign(Hash sigHash)
165         {
166             var signer = SignerUtilities.GetSigner("NONEwithECDSA");
167             signer.Init(true, _Private);
168             signer.BlockUpdate(sigHash.hashBytes, 0, sigHash.hashSize);
169
170             return signer.GenerateSignature();
171         }
172
173         public CPubKey PubKey
174         {
175             get { return new CPubKey(PublicBytes); }
176         }
177
178         /// <summary>
179         /// SecretBytes part of key pair
180         /// </summary>
181         public byte[] SecretBytes
182         {
183             get
184             {
185                 var secretBytes = new List<byte>(_Private.D.ToByteArray());
186
187                 if (secretBytes[0] == 0x00)
188                 {
189                     // Remove sign
190                     secretBytes.RemoveAt(0);
191                 }
192
193                 if (IsCompressed)
194                 {
195                     // Set compression flag
196                     secretBytes.Add(0x01);
197                 }
198
199                 return secretBytes.ToArray();
200             }
201         }
202
203         public string ToHex()
204         {
205             return Interop.ToHex(SecretBytes);
206         }
207
208         public override string ToString()
209         {
210             var r = new List<byte>();
211
212             r.Add((byte)(128 + AddrType.PUBKEY_ADDRESS)); // Key version
213             r.AddRange(SecretBytes); // Key data
214
215             return AddressTools.Base58EncodeCheck(r.ToArray());
216         }
217     }
218 }