X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=Novacoin%2FCKeyPair.cs;h=5dcedbb52455787e293a3dcd0f2bb3f5deb1783a;hb=1dcac5faa2b1477034f82466ffb16170fa2e9bb6;hp=a729d50dbe589c55553167671bdf56b7600eeeaa;hpb=be834adfb84c418d7915a186ee13651312eab1d1;p=NovacoinLibrary.git diff --git a/Novacoin/CKeyPair.cs b/Novacoin/CKeyPair.cs index a729d50..5dcedbb 100644 --- a/Novacoin/CKeyPair.cs +++ b/Novacoin/CKeyPair.cs @@ -1,18 +1,36 @@ -using System.Collections.Generic; -using System.Linq; -using System; +/** + * Novacoin classes library + * Copyright (C) 2015 Alex D. (balthazar.ad@gmail.com) -using Org.BouncyCastle.Math; -using Org.BouncyCastle.Math.EC; + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ -using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Generators; + +using System.Security.Cryptography; + using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; - +using System.Collections.Generic; +using System.Linq; +using System; +using System.Diagnostics.Contracts; namespace Novacoin { + public class CKeyPair : CKey { private ECPrivateKeyParameters _Private; @@ -20,12 +38,12 @@ namespace Novacoin /// /// Initialize new CKeyPair instance with random secret. /// - public CKeyPair(bool Compressed=true) + public CKeyPair(bool Compressed = true) { - ECKeyGenerationParameters genParams = new ECKeyGenerationParameters(domain, new SecureRandom()); - ECKeyPairGenerator generator = new ECKeyPairGenerator("ECDSA"); + var genParams = new ECKeyGenerationParameters(domain, new SecureRandom()); + var generator = new ECKeyPairGenerator("ECDSA"); generator.Init(genParams); - AsymmetricCipherKeyPair ecKeyPair = generator.GenerateKeyPair(); + var ecKeyPair = generator.GenerateKeyPair(); _Private = (ECPrivateKeyParameters)ecKeyPair.Private; _Public = (ECPublicKeyParameters)ecKeyPair.Public; @@ -41,21 +59,23 @@ namespace Novacoin /// /// Byte sequence /// Compression flag - public CKeyPair(IEnumerable secretBytes, bool Compressed=true) + public CKeyPair(byte[] secretBytes, bool Compressed=true) { + Contract.Requires(secretBytes.Length == 32, "Serialized secret key must be 32 bytes long."); + // Deserialize secret value - BigInteger D = new BigInteger(secretBytes.Take(32).ToArray()); + var D = new BigInteger(secretBytes); + // Append with zero byte if necessary if (D.SignValue == -1) { - List fixedKeyBytes = secretBytes.Take(32).ToList(); - fixedKeyBytes.Insert(0, 0x00); // prepend with sign byte - - D = new BigInteger(fixedKeyBytes.ToArray()); + var positiveKeyBytes = new byte[33]; + Array.Copy(secretBytes, 0, positiveKeyBytes, 1, 32); + D = new BigInteger(positiveKeyBytes); } // Calculate public key - ECPoint Q = curve.G.Multiply(D); + var Q = curve.G.Multiply(D); _Private = new ECPrivateKeyParameters(D, domain); _Public = new ECPublicKeyParameters(Q, domain); @@ -70,34 +90,38 @@ namespace Novacoin /// Init key pair using secret sequence of bytes /// /// Byte sequence - public CKeyPair(IEnumerable secretBytes) : - this (secretBytes.Take(32), (secretBytes.Count() == 33 && secretBytes.Last() == 0x01)) + public CKeyPair(byte[] secretBytes) : + this (secretBytes.Take(32).ToArray(), (secretBytes.Count() == 33 && secretBytes.Last() == 0x01)) { } public CKeyPair(string strBase58) { - List rawBytes = AddressTools.Base58DecodeCheck(strBase58).ToList(); - rawBytes.RemoveAt(0); // Remove key version byte + var rawSecretBytes = AddressTools.Base58DecodeCheck(strBase58); + + if (rawSecretBytes.Length != 33 && rawSecretBytes.Length != 34) + { + throw new ArgumentException("Though you have provided a correct Base58 representation of some data, this data doesn't represent a valid private key."); + } // Deserialize secret value - BigInteger D = new BigInteger(rawBytes.Take(32).ToArray()); + var D = new BigInteger(rawSecretBytes.Skip(1).Take(32).ToArray()); if (D.SignValue == -1) { - List secretbytes = rawBytes.Take(32).ToList(); // Copy secret - secretbytes.Insert(0, 0x00); // Prepend with sign byte + var secretBytes = new byte[33]; + Array.Copy(rawSecretBytes, 1, secretBytes, 1, 32); // Copying the privkey, 32 bytes starting from second byte of array - D = new BigInteger(secretbytes.ToArray()); // Try decoding again + D = new BigInteger(secretBytes); // Try decoding again } // Calculate public key - ECPoint Q = curve.G.Multiply(D); + var Q = curve.G.Multiply(D); _Private = new ECPrivateKeyParameters(D, domain); _Public = new ECPublicKeyParameters(Q, domain); - if (rawBytes.Count == 33 && rawBytes.Last() == 0x01) // Check compression tag + if (rawSecretBytes.Length == 34 && rawSecretBytes.Last() == 0x01) // Check compression tag { _Public = Compress(_Public); } @@ -116,62 +140,61 @@ namespace Novacoin /// /// Create signature for supplied data /// - /// Data bytes sequence + /// Hash to sigh /// Signature bytes sequence - public IEnumerable Sign(IEnumerable data) + public byte[] Sign(uint256 sigHash) { - byte[] dataBytes = data.ToArray(); - - ISigner signer = SignerUtilities.GetSigner("SHA-256withECDSA"); + var signer = SignerUtilities.GetSigner("NONEwithECDSA"); signer.Init(true, _Private); - signer.BlockUpdate(dataBytes, 0, dataBytes.Length); + signer.BlockUpdate(sigHash, 0, sigHash.Size); return signer.GenerateSignature(); } public CPubKey PubKey { - get { return new CPubKey(PublicBytes); } + get { return new CPubKey(_Public.Q.GetEncoded()); } } /// /// SecretBytes part of key pair /// - public IEnumerable SecretBytes + public static implicit operator byte[] (CKeyPair kp) { - get - { - List secretBytes = new List(_Private.D.ToByteArray()); - - if (secretBytes[0] == 0x00) - { - // Remove sign - secretBytes.RemoveAt(0); - } + var secretBytes = new List(kp._Private.D.ToByteArray()); - if (IsCompressed) - { - // Set compression flag - secretBytes.Add(0x01); - } + if (secretBytes.Count == 33 && secretBytes[0] == 0x00) + { + // Remove sign + secretBytes.RemoveAt(0); + } - return secretBytes; + if (kp.IsCompressed) + { + // Set compression flag + secretBytes.Add(0x01); } + + return secretBytes.ToArray(); } public string ToHex() { - return Interop.ToHex(SecretBytes); + return Interop.ToHex((byte[])this); } + /// + /// Generate Base58 string in wallet import format + /// + /// public override string ToString() { - List r = new List(); + var r = new List(); r.Add((byte)(128 + AddrType.PUBKEY_ADDRESS)); // Key version - r.AddRange(SecretBytes); // Key data + r.AddRange((byte[])this); // Key data - return AddressTools.Base58EncodeCheck(r); + return AddressTools.Base58EncodeCheck(r.ToArray()); } } }