Ejemplo n.º 1
0
        /**
         * Restore account from key and passphrase.
         *
         * @param {Key} input - Key Object.
         * @param {Password} password - Provided password.
         * @param {Boolean} nonStrict - Strict сase sensitivity flag.
         *
         * @return {@link Account} - Instance of Account restored from key and passphrase.
         */
        public Account FromKey(Key input, string password)
        {
            var json = input;

            if (json.version != KEYVERSION3 && json.version != KEYCURRENTVERSION)
            {
                throw new Exception("Not supported wallet version");
            }
            byte[]    derivedKey = null;
            KDFParams kdfparams  = new KDFParams();

            if (json.crypto.kdf == "scrypt")
            {
                kdfparams = json.crypto.kdfparams;

                //derivedKey = Replicon.Cryptography.SCrypt.SCrypt.DeriveKey(Encoding.UTF8.GetBytes(password), kdfparams.salt.HexToByteArray(), (ulong)kdfparams.n, (uint)kdfparams.r, (uint)kdfparams.p, (uint)kdfparams.dklen);
                derivedKey = ScryptUtil.Scrypt(Encoding.UTF8.GetBytes(password), kdfparams.salt.HexToByteArray(), kdfparams.n, kdfparams.r, kdfparams.p, kdfparams.dklen);
            }
            else if (json.crypto.kdf == "pbkdf2")
            {
                kdfparams = json.crypto.kdfparams;
                if (kdfparams.prf != "hmac-sha256")
                {
                    throw new Exception("Unsupported parameters to PBKDF2");
                }

                RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
                crypto.GetBytes(kdfparams.salt.HexToByteArray());
                Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(password), kdfparams.salt.HexToByteArray(), kdfparams.c);
                derivedKey = pbkdf2.GetBytes(kdfparams.dklen);
            }
            else
            {
                throw new Exception("Unsupported key derivation scheme");
            }
            var ciphertext = json.crypto.ciphertext.HexToByteArray();

            byte[] mac;

            if (json.version == KEYCURRENTVERSION)
            {
                var _derviedKey = new byte[32];
                Array.Copy(derivedKey, 16, _derviedKey, 0, 32);
                var iv     = json.crypto.cipherparams.iv.HexToByteArray();
                var cipher = json.crypto.cipher.HexToByteArray();
                var _mac   = new byte[_derviedKey.Length + ciphertext.Length + iv.Length + cipher.Length];
                Array.Copy(_derviedKey, 0, _mac, 0, _derviedKey.Length);
                Array.Copy(ciphertext, 0, _mac, _derviedKey.Length, ciphertext.Length);
                Array.Copy(iv, 0, _mac, _derviedKey.Length + ciphertext.Length, iv.Length);
                Array.Copy(cipher, 0, _mac, _derviedKey.Length + ciphertext.Length + iv.Length, cipher.Length);
                mac = Sha3Util.Get256Hash(_mac);
            }
            else
            {
                // KeyVersion3
                var _mac = new byte[derivedKey.Slice(16, 32).Length + ciphertext.Length];
                mac = Sha3Util.Get256Hash(_mac);
            }

            if (mac.ToHex() != json.crypto.mac)
            {
                throw new Exception("Key derivation failed - possibly wrong passphrase");
            }

            Aes128CTR aes = new Aes128CTR(json.crypto.cipherparams.iv.HexToByteArray());

            byte[] src  = ciphertext;
            byte[] dest = new byte[0];

            using (ICryptoTransform decrypt = aes.CreateDecryptor(derivedKey.Slice(0, 16), null))
            {
                dest = decrypt.TransformFinalBlock(src, 0, src.Length);
            }

            var _seed = new byte[src.Length + dest.Length];
            var seed  = new byte[32];

            CryptoUtils.Zeros(seed);
            Array.Copy(_seed, 0, seed, 32 - _seed.Length, _seed.Length);
            SetPrivateKey(seed);
            return(this);
        }
Ejemplo n.º 2
0
        /**
         * Generate key by passphrase and options.
         *
         * @param {Password} password - Provided password.
         * @param {KeyOptions} opts - Key options.
         *
         * @return {Key} Key Object.
         *
         * @example var key = account.toKey("passphrase");
         */
        public Key ToKey(string password, KeyOptions opts = null)
        {
            byte[] derivedKey;
            if (opts.kdf == KDFEnum.Pbkdf2)
            {
                RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
                crypto.GetBytes(opts.salt);
                Rfc2898DeriveBytes pbkdf2 = new Rfc2898DeriveBytes(password, opts.salt, opts.c);
                derivedKey = pbkdf2.GetBytes(opts.dklen);
            }
            else if (opts.kdf == KDFEnum.Scrypt)
            {
                //derivedKey = Replicon.Cryptography.SCrypt.SCrypt.DeriveKey(Encoding.UTF8.GetBytes(password), opts.salt, (ulong)opts.n, (uint)opts.r, (uint)opts.p, (uint)opts.dklen);

                derivedKey = ScryptUtil.Scrypt(Encoding.UTF8.GetBytes(password), opts.salt, opts.n, opts.r, opts.p, opts.dklen);
            }
            else
            {
                throw new Exception("Unsupported kdf");
            }


            var       iv  = opts.iv.Slice(0, opts.iv.Length);
            Aes128CTR aes = new Aes128CTR(iv);

            byte[] key = derivedKey.Slice(0, 16);
            byte[] src = GetPrivateKey();
            byte[] dest;

            using (ICryptoTransform encrypt = aes.CreateEncryptor(key, null))
            {
                dest = encrypt.TransformFinalBlock(src, 0, src.Length);
                //encrypt.TransformBlock(src, 0, src.Length, dest, 0);
            }


            byte[] ciphertext = ByteUtil.Merge(dest, new byte[] { });


            var algoStr = opts.cipher;
            var algoBuf = Encoding.UTF8.GetBytes(algoStr);

            var data = ByteUtil.Merge(derivedKey.Slice(16, 32), ciphertext, opts.iv, algoBuf);

            bool bl = data.Compare(new byte[] { 29, 52, 224, 140, 175, 174, 254, 246, 150, 111, 54, 131, 20, 66, 32, 30, 74, 150, 12, 191, 5, 61, 192, 196, 41, 236, 65, 21, 61, 184, 251, 34, 181, 156, 116, 62, 192, 63, 123, 193, 144, 210, 110, 229, 144, 235, 148, 57, 174, 176, 29, 188, 185, 223, 149, 83, 130, 30, 94, 120, 100, 252, 2, 217, 97, 101, 115, 45, 49, 50, 56, 45, 99, 116, 114 });

            byte[] mac = Sha3Util.Get256Hash(data);

            return(new Key
            {
                version = KEYCURRENTVERSION,
                id = Guid.NewGuid().ToString(),
                address = GetAddressString(),
                crypto = new KeyCrypto
                {
                    ciphertext = ciphertext.ToHex(),
                    cipherparams = new CipherParams()
                    {
                        iv = opts.iv.ToHex()
                    },
                    cipher = opts.cipher,
                    kdf = Enum.GetName(typeof(KDFEnum), opts.kdf).ToLower(),
                    kdfparams = new KDFParams {
                        c = opts.c,
                        salt = opts.salt.ToHex(),
                        dklen = opts.dklen,
                        n = opts.n,
                        p = opts.p,
                        prf = (opts.kdf == KDFEnum.Pbkdf2) ? "hmac-sha256" : "",
                        r = opts.r
                    },
                    mac = mac.ToHex(),
                    machash = "sha3256"
                }
            });
        }