2 * Novacoin classes library
3 * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com)
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.
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.
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/>.
19 using Org.BouncyCastle.Crypto;
20 using Org.BouncyCastle.Crypto.Generators;
22 using System.Security.Cryptography;
24 using Org.BouncyCastle.Crypto.Parameters;
25 using Org.BouncyCastle.Math;
26 using Org.BouncyCastle.Security;
27 using System.Collections.Generic;
33 public class CKeyPair : CKey
35 private ECPrivateKeyParameters _Private;
36 private RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
39 /// Initialize new CKeyPair instance with random secret.
41 public CKeyPair(bool Compressed = true)
45 var genParams = new ECKeyGenerationParameters(domain, new SecureRandom());
46 var generator = new ECKeyPairGenerator("ECDSA");
47 generator.Init(genParams);
48 var ecKeyPair = generator.GenerateKeyPair();
50 _Private = (ECPrivateKeyParameters)ecKeyPair.Private;
51 _Public = (ECPublicKeyParameters)ecKeyPair.Public;
55 var buffer1 = new byte[32];
56 var buffer2 = new byte[32];
60 rng.GetBytes(buffer1);
61 rng.GetNonZeroBytes(buffer2);
63 D = new BigInteger(Hash256.ComputeRaw256(ref buffer1, ref buffer2));
65 if (D.BitLength < 249)
66 System.Console.WriteLine(D.BitLength);
68 while (D.SignValue == -1);
70 var Q = curve.G.Multiply(D);
72 _Private = new ECPrivateKeyParameters(D, domain);
73 _Public = new ECPublicKeyParameters(Q, domain);
78 _Public = Compress(_Public);
83 /// Init key pair using secret sequence of bytes
85 /// <param name="secretBytes">Byte sequence</param>
86 /// <param name="Compressed">Compression flag</param>
87 public CKeyPair(byte[] secretBytes, bool Compressed=true)
89 // Deserialize secret value
90 var D = new BigInteger(secretBytes.Take(32).ToArray());
92 if (D.SignValue == -1)
94 var fixedKeyBytes = secretBytes.Take(32).ToList();
95 fixedKeyBytes.Insert(0, 0x00); // prepend with sign byte
97 D = new BigInteger(fixedKeyBytes.ToArray());
100 // Calculate public key
101 var Q = curve.G.Multiply(D);
103 _Private = new ECPrivateKeyParameters(D, domain);
104 _Public = new ECPublicKeyParameters(Q, domain);
108 _Public = Compress(_Public);
113 /// Init key pair using secret sequence of bytes
115 /// <param name="secretBytes">Byte sequence</param>
116 public CKeyPair(byte[] secretBytes) :
117 this (secretBytes.Take(32).ToArray(), (secretBytes.Count() == 33 && secretBytes.Last() == 0x01))
121 public CKeyPair(string strBase58)
123 var rawBytes = AddressTools.Base58DecodeCheck(strBase58).ToList();
124 rawBytes.RemoveAt(0); // Remove key version byte
126 // Deserialize secret value
127 var D = new BigInteger(rawBytes.Take(32).ToArray());
129 if (D.SignValue == -1)
131 var secretbytes = rawBytes.Take(32).ToList(); // Copy secret
132 secretbytes.Insert(0, 0x00); // Prepend with sign byte
134 D = new BigInteger(secretbytes.ToArray()); // Try decoding again
137 // Calculate public key
138 var Q = curve.G.Multiply(D);
140 _Private = new ECPrivateKeyParameters(D, domain);
141 _Public = new ECPublicKeyParameters(Q, domain);
143 if (rawBytes.Count == 33 && rawBytes.Last() == 0x01) // Check compression tag
145 _Public = Compress(_Public);
150 /// Initialize a copy of CKeyPair instance
152 /// <param name="pair">CKyPair instance</param>
153 public CKeyPair(CKeyPair pair)
155 _Public = pair._Public;
156 _Private = pair._Private;
160 /// Create signature for supplied data
162 /// <param name="data">Hash to sigh</param>
163 /// <returns>Signature bytes sequence</returns>
164 public byte[] Sign(Hash sigHash)
166 var signer = SignerUtilities.GetSigner("NONEwithECDSA");
167 signer.Init(true, _Private);
168 signer.BlockUpdate(sigHash.hashBytes, 0, sigHash.hashSize);
170 return signer.GenerateSignature();
173 public CPubKey PubKey
175 get { return new CPubKey(PublicBytes); }
179 /// SecretBytes part of key pair
181 public byte[] SecretBytes
185 var secretBytes = new List<byte>(_Private.D.ToByteArray());
187 if (secretBytes[0] == 0x00)
190 secretBytes.RemoveAt(0);
195 // Set compression flag
196 secretBytes.Add(0x01);
199 return secretBytes.ToArray();
203 public string ToHex()
205 return Interop.ToHex(SecretBytes);
208 public override string ToString()
210 var r = new List<byte>();
212 r.Add((byte)(128 + AddrType.PUBKEY_ADDRESS)); // Key version
213 r.AddRange(SecretBytes); // Key data
215 return AddressTools.Base58EncodeCheck(r.ToArray());