public static PrivateKeyNotWallet Decrypt(string encoded, string password, Network network) { var decoded = Encoders.Base58Check.DecodeData(encoded); var version = decoded.SafeSubarray(0, 1); var flag = decoded.SafeSubarray(1, 1); var addresshash = decoded.SafeSubarray(2, 4); var encrypted = decoded.SafeSubarray(6, 32); var expected = network.GetVersionBytes(Network.VersionByte.BIP38_ENCRYPTED_PRIVATE_KEY); if (!Utils.ArrayEqual(version, expected)) { throw new ArgumentException("Invalid version"); } if (!Utils.ArrayEqual(flag, new[] { FLAG })) { throw new ArgumentException("Invalid flag"); } var derived = SCrypt.BitcoinComputeDerivedKey(Encoding.UTF8.GetBytes(password), addresshash); var keyBytes = Bip38Engine.DecryptKey(encrypted, derived); var key = PrivateKeyNotWallet.FromBytes(keyBytes); var addressBytes = Encoders.ASCII.DecodeData(key.PublicKey.GetAddress().Encoded); var salt = Hashes.Hash256(addressBytes).ToBytes().SafeSubarray(0, 4); if (!Utils.ArrayEqual(salt, addresshash)) { throw new ArgumentException("Invalid password (or invalid Network)"); } return(key); }
public static string Encrypt(PrivateKeyNotWallet key, string password, Network network) { var version = network.GetVersionBytes(Network.VersionByte.BIP38_ENCRYPTED_PRIVATE_KEY); var vch = key.PrivateKey.GetBytes(); //Compute the Bitcoin address (ASCII), var addressBytes = Encoders.ASCII.DecodeData(key.PublicKey.GetAddress().Encoded); // and take the first four bytes of SHA256(SHA256()) of it. Let's call this "addresshash". var addresshash = Hashes.Hash256(addressBytes).ToBytes().SafeSubarray(0, 4); var derived = SCrypt.BitcoinComputeDerivedKey(Encoding.UTF8.GetBytes(password), addresshash); var encrypted = Bip38Engine.EncryptKey(vch, derived); //flagByte |= (key.IsCompressed ? (byte)0x20 : (byte)0x00); // WTF OR 0x00 is IDENTITY var bytes = version .Concat(new[] { FLAG }) .Concat(addresshash) .Concat(encrypted).ToArray(); return(Encoders.Base58Check.EncodeData(bytes)); }