示例#1
0
        /// Derive an extended key from an extended key
        public ExtendedKey Derive(Secp256K1 secp, uint n)

        {
            var nBytes = BitConverter.GetBytes(n);

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(nBytes);
            }

            var seed = ByteUtil.Combine(Key.Value, nBytes);

            var blake2B = new HMACBlake2B(Chaincode, 64 * 8);

            var derived = blake2B.ComputeHash(seed);

            var secretKey = SecretKey.From_slice(secp, derived.Take(32).ToArray());

            secretKey.Add_assign(secp, Key);

            // TODO check if key != 0 ?

            var chainCode = derived.Skip(32).Take(32).ToArray();

            return(new ExtendedKey
            {
                Depth = (byte)(Depth + 1),
                RootKeyId = Identifier(secp),
                NChild = n,
                Chaincode = chainCode,
                Key = secretKey
            });
        }
示例#2
0
        public static ExtendedKey from_slice(Secp256K1 secp, byte[] slice)
        {
            // TODO change when ser. ext. size is fixed
            if (slice.Length != 79)
            {
                throw new Exception("InvalidSliceSize");
            }

            var ext = new ExtendedKey {
                Depth = slice[0]
            };

            var rootKeyBytes = slice.Skip(1).Take(10).ToArray();

            ext.RootKeyId = ExtKey.Identifier.From_bytes(rootKeyBytes);

            var nchildBytes = slice.Skip(11).Take(4).ToArray();

            Array.Reverse(nchildBytes);
            ext.NChild = BitConverter.ToUInt32(nchildBytes, 0);

            ext.Chaincode = slice.Skip(15).Take(32).ToArray();

            var keyBytes = slice.Skip(47).Take(32).ToArray();


            ext.Key = SecretKey.From_slice(secp, keyBytes);

            return(ext);
        }
示例#3
0
        public void Invalid_secret_key()
        {
            var s = Secp256K1.New();

            // Zero
            var ex = Assert.Throws <Exception>(() => { SecretKey.From_slice(s, ByteUtil.Get_bytes(0, 32)); });

            Assert.Equal("InvalidSecretKey", ex.Message);
            // -1
            ex = Assert.Throws <Exception>(() => { SecretKey.From_slice(s, ByteUtil.Get_bytes(0xff, 32)); });
            Assert.Equal("InvalidSecretKey", ex.Message);

            // Top of range
            var sk1 = SecretKey.From_slice(s, new byte[]
            {
                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
                0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
                0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40
            });

            Assert.NotEmpty(sk1.Value);

            // One past top of range
            Assert.Throws <Exception>(() =>
            {
                SecretKey.From_slice(s, new byte[]
                {
                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
                    0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
                    0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
                });
            });
        }
示例#4
0
        public void Sign()
        {
            var s = Secp256K1.New();

            s.Randomize(RandomNumberGenerator.Create());

            var one = new byte[]
            {
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
            };

            var sk  = SecretKey.From_slice(s, one);
            var msg = Message.from_slice(one);

            var sig  = s.sign_recoverable(msg, sk);
            var rsig = RecoverableSigniture.From_compact(s, new byte[]
            {
                0x66, 0x73, 0xff, 0xad, 0x21, 0x47, 0x74, 0x1f,
                0x04, 0x77, 0x2b, 0x6f, 0x92, 0x1f, 0x0b, 0xa6,
                0xaf, 0x0c, 0x1e, 0x77, 0xfc, 0x43, 0x9e, 0x65,
                0xc3, 0x6d, 0xed, 0xf4, 0x09, 0x2e, 0x88, 0x98,
                0x4c, 0x1a, 0x97, 0x16, 0x52, 0xe0, 0xad, 0xa8,
                0x80, 0x12, 0x0e, 0xf8, 0x02, 0x5e, 0x70, 0x9f,
                0xff, 0x20, 0x80, 0xc4, 0xa3, 0x9a, 0xae, 0x06,
                0x8d, 0x12, 0xee, 0xd0, 0x09, 0xb6, 0x8c, 0x89
            },
                                                         RecoveryId.from_i32(1));

            Assert.Equal(sig.Value, rsig.Value);
        }
示例#5
0
        /// Computes the sum of multiple positive and negative blinding factors.
        public static SecretKey blind_sum(this Secp256K1 self, SecretKey[] positive, SecretKey[] negative)
        {
            //var neg = new byte[negative.Length][];


            var all = new byte[positive.Length + negative.Length][];

            for (var i = 0; i < positive.Length; i++)
            {
                all[i] = positive[i].Value;
            }
            for (var i = 0; i < negative.Length; i++)
            {
                all[positive.Length + i] = negative[i].Value;
            }


            var ret = new byte[32];

            var err = Proxy.secp256k1_pedersen_blind_sum(
                self.Ctx,
                ret,
                all,
                all.Length,
                positive.Length);


            if (err == 1)
            {
                return(SecretKey.From_slice(self, ret));
            }

            // secp256k1 should never return an invalid private
            throw new Exception("This should never happen!");
        }
示例#6
0
        public void Extkey_derivation()
        {
            // TODO More test vectors
            var s       = Secp256K1.New();
            var seed    = HexUtil.from_hex("000102030405060708090a0b0c0d0e0f");
            var extk    = ExtendedKey.from_seed(s, seed);
            var derived = extk.Derive(s, 0);
            var sec     = HexUtil.from_hex("d75f70beb2bd3b56f9b064087934bdedee98e4b5aae6280c58b4eff38847888f"
                                           );
            var        secretKey  = SecretKey.From_slice(s, sec);
            var        chaincode  = HexUtil.from_hex("243cb881e1549e714db31d23af45540b13ad07941f64a786bbf3313b4de1df52");
            var        rootKeyId  = HexUtil.from_hex("83e59c48297b78b34b73");
            var        identifier = HexUtil.from_hex("0185adb4d8b730099c93");
            const int  depth      = 1;
            const uint nChild     = 0;

            Assert.Equal(derived.Key.Value, secretKey.Value);
            Assert.Equal(
                derived.Identifier(s).Value,
                Identifier.From_bytes(identifier).Value
                );
            Assert.Equal(
                derived.RootKeyId.Value,
                Identifier.From_bytes(rootKeyId).Value
                );
            Assert.Equal(derived.Chaincode, chaincode);
            Assert.Equal(derived.Depth, depth);
            Assert.Equal(derived.NChild, nChild);
        }
示例#7
0
        // For tests and burn only, associate a key identifier with a known secret key.
        //
        public static Keychain Burn_enabled(Keychain keychain, Identifier burnKeyId)
        {
            var keyOverridesNew =
                new Dictionary <string, SecretKey> {
                { burnKeyId.HexValue, SecretKey.From_slice(keychain.Secp, new byte[32]) }
            };

            return(new Keychain(keychain.Secp, keychain.Extkey.Clone(), keyOverridesNew, keychain.KeyDerivationCache));
        }
示例#8
0
        public void Keypair_slice_round_trip()
        {
            var secp256K1 = Secp256K1.New();

            // ReSharper disable once JoinDeclarationAndInitializer
            SecretKey sk;

            var ex = Assert.Throws <Exception>(
                () => { sk = SecretKey.From_slice(secp256K1, ByteUtil.Get_bytes(1, 31)); });

            Assert.Equal("InvalidSecretKey", ex.Message);

            sk = SecretKey.From_slice(secp256K1, ByteUtil.Get_bytes(1, 32));

            Assert.NotEmpty(sk.Value);
        }
示例#9
0
        /// Creates a new extended master key from a seed
        public static ExtendedKey from_seed(Secp256K1 secp, byte[] seed)
        {
            switch (seed.Length)
            {
            case 16:
            case 32:
            case 64:

                break;

            default:
                throw new Exception("InvalidSeedSize");
            }

            var keyData = Encoding.ASCII.GetBytes("Mimble seed");

            var blake2B = new HMACBlake2B(keyData, 512);

            var derived = blake2B.ComputeHash(seed);

            var chaincode = derived.Skip(32).ToArray();

            var secretKeyBytes = derived.Take(32).ToArray();

            var secretKey = SecretKey.From_slice(secp, secretKeyBytes);

            var ext = new ExtendedKey
            {
                Depth     = 0,
                RootKeyId = ExtKey.Identifier.Zero(),
                NChild    = 0,
                Chaincode = chaincode,
                Key       = secretKey,
            };

            ext.RootKeyId = ext.Identifier(secp);

            return(ext);
        }
示例#10
0
        public void Extkey_from_seed()
        {
            // TODO More test vectors
            var s         = Secp256K1.New();
            var seed      = HexUtil.from_hex("000102030405060708090a0b0c0d0e0f");
            var extk      = ExtendedKey.from_seed(s, seed);
            var sec       = HexUtil.from_hex("c3f5ae520f474b390a637de4669c84d0ed9bbc21742577fac930834d3c3083dd");
            var secretKey = SecretKey.From_slice(s, sec);
            var chaincode = HexUtil.from_hex("e7298e68452b0c6d54837670896e1aee76b118075150d90d4ee416ece106ae72");


            var        identifier = HexUtil.from_hex("83e59c48297b78b34b73");
            const int  depth      = 0;
            const uint nChild     = 0;

            Assert.Equal(extk.Key.Value, secretKey.Value);
            Assert.Equal(extk.Identifier(s).Value, Identifier.From_bytes(identifier).Value);
            Assert.Equal(extk.RootKeyId.Value, Identifier.From_bytes(identifier).Value);
            Assert.Equal(extk.Chaincode, chaincode);
            Assert.Equal(extk.Depth, depth);
            Assert.Equal(extk.NChild, nChild);
        }
示例#11
0
        public void Capabilities()
        {
            var none = Secp256K1.WithCaps(ContextFlag.None);
            var sign = Secp256K1.WithCaps(ContextFlag.SignOnly);
            var vrfy = Secp256K1.WithCaps(ContextFlag.VerifyOnly);
            var full = Secp256K1.WithCaps(ContextFlag.Full);

            var msgBytes = ByteUtil.Get_bytes(0, 32);
            var msg      = Message.from_slice(msgBytes);
            var rng      = RandomNumberGenerator.Create();

            // Try key generation
            var ex = Assert.Throws <Exception>(() => { none.generate_keypair(rng); });

            Assert.Equal("IncapableContext", ex.Message);
            ex = Assert.Throws <Exception>(() => { vrfy.generate_keypair(rng); });
            Assert.Equal("IncapableContext", ex.Message);

            sign.generate_keypair(rng);

            var fullKp = full.generate_keypair(rng);
            var sk     = fullKp.secretKey;
            var pk     = fullKp.publicKey;

            // Try signing
            ex = Assert.Throws <Exception>(() => { none.Sign(msg, sk); });
            Assert.Equal("IncapableContext", ex.Message);
            ex = Assert.Throws <Exception>(() => { vrfy.Sign(msg, sk); });
            Assert.Equal("IncapableContext", ex.Message);

            var ss = sign.Sign(msg, sk);
            var fs = full.Sign(msg, sk);

            Assert.Equal(ss.Value, fs.Value);

            ex = Assert.Throws <Exception>(() => { none.sign_recoverable(msg, sk); });
            Assert.Equal("IncapableContext", ex.Message);
            ex = Assert.Throws <Exception>(() => { vrfy.sign_recoverable(msg, sk); });
            Assert.Equal("IncapableContext", ex.Message);

            var srs = sign.sign_recoverable(msg, sk);
            var fsr = full.sign_recoverable(msg, sk);

            Assert.Equal(srs.Value, fsr.Value);

            var sig  = full.Sign(msg, sk);
            var sigr = full.sign_recoverable(msg, sk);

            // Try verifying
            ex = Assert.Throws <Exception>(() => { none.Verify(msg, sig, pk); });
            Assert.Equal("IncapableContext", ex.Message);
            ex = Assert.Throws <Exception>(() => { sign.Verify(msg, sig, pk); });
            Assert.Equal("IncapableContext", ex.Message);

            vrfy.Verify(msg, sig, pk);
            full.Verify(msg, sig, pk);

            // Try pk recovery
            ex = Assert.Throws <Exception>(() => { none.Recover(msg, sigr); });
            Assert.Equal("IncapableContext", ex.Message);
            ex = Assert.Throws <Exception>(() => { sign.Recover(msg, sigr); });
            Assert.Equal("IncapableContext", ex.Message);

            var vrc = vrfy.Recover(msg, sigr);
            var frc = full.Recover(msg, sigr);

            Assert.Equal(vrc.Value, frc.Value);
            Assert.Equal(frc.Value, pk.Value);

            // Check that we can produce keys from slices with no precomputation
            var pkSlice = pk.serialize_vec(none, false);
            var skSlice = sk.Value;
            var newPk   = PublicKey.from_slice(none, pkSlice);
            var newSk   = SecretKey.From_slice(none, skSlice);

            Assert.Equal(sk.Value, newSk.Value);
            Assert.Equal(pk.Value, newPk.Value);

            none.Dispose();
            sign.Dispose();
            vrfy.Dispose();
            full.Dispose();
        }
示例#12
0
 public static BlindingFactor from_slice(Secp256K1 secp, byte[] data)
 {
     return(new BlindingFactor(SecretKey.From_slice(secp, data)));
 }