public static void GenerateKeyPair( SecureBytes seed, out SecureBytes privateKey, out SecureBytes publicKey) { using var scopedSeed = seed.ToUnsecuredBytes(); using var scopedPrivateKey = new ScopedBytes(PrivateKeySize); using var scopedPublicKey = new ScopedBytes(PublicKeySize); // copy first 32-bytes from seed to expandedPrivateKey left part ([0-31] bytes) Array.Copy( sourceArray: scopedSeed, sourceIndex: 0, destinationArray: scopedPrivateKey, destinationIndex: 0, length: PrivateKeySize); // use first 32-bytes from seed (private key) to generate public key GeneratePublicKey( sk: scopedSeed, skOff: 0, pk: scopedPublicKey, pkOff: 0); privateKey = new SecureBytes(scopedPrivateKey); publicKey = new SecureBytes(scopedPublicKey); }
public TezosExtKey(SecureBytes seed) { using var scopedSeed = seed.ToUnsecuredBytes(); //var masterSecret = Hashes.HMACSHA512(key: HashKey, data: seed); using var masterSecret = new ScopedBytes(PrivateKeyLength); Buffer.BlockCopy( src: scopedSeed, srcOffset: 0, dst: masterSecret, dstOffset: 0, count: 32); // check third highest bit of the last byte of kL, where // k = H512(masterSecret) and kL is its left 32-bytes while (true) { using var k = new ScopedBytes(Hashes.SHA512(masterSecret)); if ((k[31] & 0b00100000) > 0) { // discard current k and try to get new Buffer.BlockCopy( src: k, srcOffset: 0, dst: masterSecret, dstOffset: 0, count: 32); }
/// <exception cref="SerializationException">An object in the graph of type parameter <typeparamref name="T"/> is not marked as serializable.</exception> private T ReadObject(int len) { var data = new byte[len]; BaseStream.Read(data, 0, len); //Check if we have to decrypt this data first if (ProtectedEncryptionKey != null) { var key = SecureBytes.Unprotect(ProtectedEncryptionKey); try { var encryptedData = DecryptBytes(data, key); Array.Clear(data, 0, data.Length); data = encryptedData; } finally { Array.Clear(key, 0, key.Length); } } using (var memoryStream = new MemoryStream(data)) { var result = (T)_binaryFormatter.Deserialize(memoryStream); Array.Clear(data, 0, data.Length); return(result); } }
/// <exception cref="SerializationException">An object in the graph of type parameter <typeparamref name="T"/> is not marked as serializable.</exception> private byte[] Serialize(T obj) { try { using (var memoryStream = new MemoryStream()) { _binaryFormatter.Serialize(memoryStream, obj); //Check if we should return an encrypted array of data instead if (ProtectedEncryptionKey != null) { var key = SecureBytes.Unprotect(ProtectedEncryptionKey); try { return(EncryptStream(memoryStream, key)); } finally { Array.Clear(key, 0, key.Length); } } return(memoryStream.ToArray()); } } catch { //if any exception in the serialize, it will stop named pipe wrapper, so there will ignore any exception. return(null); } }
private Task <bool> SignAsync(SecureBytes privateKey) { if (privateKey == null) { throw new ArgumentNullException(nameof(privateKey)); } using var scopedPrivateKey = privateKey.ToUnsecuredBytes(); var chain = ((Atomex.Ethereum)Currency).Chain; RlpEncodedTx = Web3.OfflineTransactionSigner .SignTransaction( privateKey: scopedPrivateKey, chain: chain, to: To, amount: Amount, nonce: Nonce, gasPrice: GasPrice, gasLimit: GasLimit, data: Input); From = Web3.OfflineTransactionSigner .GetSenderAddress(RlpEncodedTx, chain) .ToLowerInvariant(); return(Task.FromResult(true)); }
public HdKeyStorage Unlock(SecureString password) { try { using var scopedSeed = new ScopedBytes(Aes.Decrypt( encryptedBytes: Hex.FromString(EncryptedSeed), password: password, keySize: AesKeySize, saltSize: AesSaltSize, iterations: AesRfc2898Iterations)); Seed = new SecureBytes(scopedSeed); foreach (var singleKey in NonHdKeys) { singleKey.Unlock(password); } } catch (Exception e) { Log.Error(e, "Unlock error"); } return(this); }
public TezosKey(SecureBytes seed) { Ed25519.GenerateKeyPair( seed: seed, privateKey: out _privateKey, publicKey: out _publicKey); }
public async Task <Result <decimal> > GetFa12AllowanceAsync( string holderAddress, string spenderAddress, string callingAddress, SecureBytes securePublicKey, CancellationToken cancellationToken = default) { var tokenConfig = _currency as Fa12Config; try { var rpc = new Rpc(_rpcNodeUri); var tx = new TezosTransaction { Currency = tokenConfig.Name, From = callingAddress, To = tokenConfig.TokenContractAddress, Fee = 0, //token.GetAllowanceFee, GasLimit = tokenConfig.GetAllowanceGasLimit, StorageLimit = 0, //token.GetAllowanceStorageLimit, Params = CreateGetAllowanceParams(holderAddress, spenderAddress, tokenConfig.ViewContractAddress), UseRun = false, UseOfflineCounter = false }; _ = await tx .FillOperationsAsync( securePublicKey : securePublicKey, tezosConfig : tokenConfig, cancellationToken : cancellationToken) .ConfigureAwait(false); var runResults = await rpc .RunOperations(tx.Head, tx.Operations) .ConfigureAwait(false); return(runResults ?["contents"] ?.LastOrDefault() ?["metadata"] ?["internal_operation_results"] ?[0] ?["result"] ?["errors"] ?[1] ?["with"] ?["args"] ?[0] ?["args"] ?[0] ?["int"] ?.Value <decimal>() ?? 0); } catch (Exception e) { return(new Error(Errors.RequestError, e.Message)); } }
public void Sign( SecureBytes privateKey, ITxOutput[] spentOutputs, BitcoinBasedConfig bitcoinBasedConfig) { using var scopedPrivateKey = privateKey.ToUnsecuredBytes(); Sign(new Key(scopedPrivateKey), spentOutputs, bitcoinBasedConfig); // todo: do not use NBitcoin.Key }
public void Lock() { Seed.Dispose(); Seed = null; foreach (var singleKey in NonHdKeys) { singleKey.Lock(); } }
public void CloneTest() { var bytes = new byte[] { 0x00, 0x01, 0x02, 0x03 }; using var secureBytes = new SecureBytes(bytes); using var clone = secureBytes.Clone(); using var cloneBytes = clone.ToUnsecuredBytes(); Assert.Equal(bytes, cloneBytes); }
public static void GeneratePublicKeyFromExtended( SecureBytes extendedPrivateKey, out SecureBytes publicKey) { using var scopedExtentedPrivateKey = extendedPrivateKey.ToUnsecuredBytes(); using var scopedPublicKey = new ScopedBytes(PointBytes); ScalarMultBaseEncoded(scopedExtentedPrivateKey, scopedPublicKey, 0); publicKey = new SecureBytes(scopedPublicKey); }
public async Task <Result <decimal> > TryGetTokenBalanceAsync( string address, string callingAddress, SecureBytes securePublicKey, int attempts = 3, int attemptsIntervalMs = 1000, CancellationToken cancellationToken = default) { return(await ResultHelper.TryDo((c) => GetTokenBalanceAsync(address, callingAddress, securePublicKey, c), attempts, attemptsIntervalMs, cancellationToken) .ConfigureAwait(false) ?? new Error(Errors.RequestError, $"Connection error while getting balance after {attempts} attempts")); }
public void FromBytesArrayTest() { const string Phrase = "return auction present awesome blast excess receive obtain explain spider iron hip curtain recipe tent aim bonus hip cliff shrug lyrics pass right spend"; var seed = new Mnemonic(Phrase).DeriveSeed(); using var secureSeed = new SecureBytes(seed); using var scopedSeed = secureSeed.ToUnsecuredBytes(); Assert.Equal(seed, scopedSeed); }
public HdKeyStorage( string mnemonic, Wordlist wordList = null, SecureString passPhrase = null, Network network = Network.MainNet) { Version = CurrentVersion; Network = network; using var scopedSeed = new ScopedBytes(new Mnemonic(mnemonic, wordList) .DeriveSeed(passPhrase.ToUnsecuredString())); Seed = new SecureBytes(scopedSeed); }
public static void GeneratePublicKey( SecureBytes privateKey, out SecureBytes publicKey) { using var scopedPrivateKey = privateKey.ToUnsecuredBytes(); using var scopedPublicKey = new ScopedBytes(PublicKeySize); GeneratePublicKey( sk: scopedPrivateKey, skOff: 0, pk: scopedPublicKey, pkOff: 0); publicKey = new SecureBytes(scopedPublicKey); }
public async Task <Result <decimal> > GetTokenAllowanceAsync( string holderAddress, string spenderAddress, string callingAddress, SecureBytes securePublicKey, CancellationToken cancellationToken = default) { var token = _currency as TezosTokens.FA12; try { var rpc = new Rpc(_rpcNodeUri); var head = await rpc .GetHeader() .ConfigureAwait(false); var tx = new TezosTransaction { Currency = token, From = callingAddress, To = token.TokenContractAddress, Fee = 0, //token.GetAllowanceFee, GasLimit = token.GetAllowanceGasLimit, StorageLimit = 0, //token.GetAllowanceStorageLimit, Params = GetAllowanceParams(holderAddress, spenderAddress, token.ViewContractAddress), }; await tx.FillOperationsAsync( head : head, securePublicKey : securePublicKey, incrementCounter : false, cancellationToken : cancellationToken) .ConfigureAwait(false); var runResults = await rpc .RunOperations(head, tx.Operations) .ConfigureAwait(false); Log.Debug("getTokenAllowance result {@result}", runResults); return(runResults?["contents"]?.LastOrDefault()?["metadata"]?["internal_operation_results"]?[0]?["result"]?["errors"]?[1]?["with"]?["args"]?[0]?["args"]?[0]?["int"]?.Value <decimal>()); } catch (Exception e) { return(new Error(Errors.RequestError, e.Message)); } }
public void BitcoinBasedExtKeyTest() { var messageBytes = Encoding.UTF8.GetBytes(Message); using var seed = new SecureBytes(new Mnemonic(Mnemonic).DeriveSeed()); using var extKey = new BitcoinBasedExtKey(seed); using var childKey = extKey.Derive(new KeyPath("m/44'/0'/0'/0'")); using var secureChildPublicKey = childKey.GetPublicKey(); using var childPublicKey = secureChildPublicKey.ToUnsecuredBytes(); var signature = childKey.SignMessage(messageBytes); Assert.True(childKey.VerifyMessage(messageBytes, signature)); var address = Common.CurrenciesTestNet.Get <BitcoinConfig>("BTC").AddressFromKey(childPublicKey); Assert.NotNull(address); }
public void Unlock(SecureString password) { try { using var scopedSeed = new ScopedBytes(Aes.Decrypt( encryptedBytes: Hex.FromString(EncryptedSeed), password: password, keySize: AesKeySize, saltSize: AesSaltSize, iterations: AesRfc2898Iterations)); Seed = new SecureBytes(scopedSeed); } catch (Exception e) { Log.Error(e, "Unlock error"); } }
private void Derive( byte[] chainCode, uint child, out byte[] childChainCode, out SecureBytes childPrivateKey, out SecureBytes childPublicKey) { using var scopedPublicKey = _publicKey.ToUnsecuredBytes(); using var scopedPrivateKey = _privateKey.ToUnsecuredBytes(); using var data = new ScopedBytes(1 + 32 + 4); if (child >> 31 == 0) { data[0] = 0; Buffer.BlockCopy(src: scopedPublicKey, srcOffset: 0, dst: data, dstOffset: 1, count: 32); } else // hardened key (private derivation) { data[0] = 0; Buffer.BlockCopy(src: scopedPrivateKey, srcOffset: 0, dst: data, dstOffset: 1, count: 32); } Buffer.BlockCopy(src: IndexToBytes(child), srcOffset: 0, dst: data, dstOffset: 33, count: 4); using var l = new ScopedBytes(Hashes.HMACSHA512(chainCode, data)); using var scopedChildPrivateKey = new ScopedBytes(l.Data.SubArray(start: 0, length: 32)); childPrivateKey = new SecureBytes(scopedChildPrivateKey); childChainCode = new byte[ChainCodeLength]; Buffer.BlockCopy( src: l, srcOffset: 32, dst: childChainCode, dstOffset: 0, count: ChainCodeLength); Ed25519.GeneratePublicKey( privateKey: childPrivateKey, publicKey: out childPublicKey); }
public void TezosExtKeyDerivationTest() { var messageBytes = Encoding.UTF8.GetBytes(Message); using var seed = new SecureBytes(new Mnemonic(Mnemonic).DeriveSeed()); using var extKey = new Bip32TezosExtKey(seed); for (var i = 0; i < 100; ++i) { using var childKey = extKey.Derive(new KeyPath($"m/44'/1729'/0'/0/{i}")); using var secureChildPublicKey = childKey.GetPublicKey(); using var childPublicKey = secureChildPublicKey.ToUnsecuredBytes(); var signature = childKey.SignMessage(messageBytes); Assert.True(childKey.VerifyMessage(messageBytes, signature)); var address = Common.CurrenciesTestNet.Get <TezosConfig>("XTZ").AddressFromKey(childPublicKey); Assert.NotNull(address); } }
public TezosExtKey(SecureBytes seed) { using var scopedSeed = seed.ToUnsecuredBytes(); using var scopedHashSeed = new ScopedBytes(Hashes.HMACSHA512(HashKey, scopedSeed)); using var secureHashSeed = new SecureBytes(scopedHashSeed); Ed25519.GenerateKeyPair( seed: secureHashSeed, privateKey: out _privateKey, publicKey: out _publicKey); ChainCode = new byte[ChainCodeLength]; // copy hashSeed last 32 bytes to ChainCode Buffer.BlockCopy( src: scopedHashSeed, srcOffset: PrivateKeyLength, dst: ChainCode, dstOffset: 0, count: ChainCodeLength); }
private TezosExtKey( SecureBytes privateKey, SecureBytes publicKey, byte depth, uint child, byte[] chainCode, uint fingerPrint) { _privateKey = privateKey; _publicKey = publicKey; Depth = depth; Child = child; Fingerprint = fingerPrint; ChainCode = new byte[ChainCodeLength]; Buffer.BlockCopy( src: chainCode, srcOffset: 0, dst: ChainCode, dstOffset: 0, count: ChainCodeLength); }
public override IExtKey CreateExtKey(SecureBytes seed) { //return new TrustWalletTezosExtKey(seed); return(new TezosExtKey(seed)); }
public override IKey CreateKey(SecureBytes seed) { return(new TezosKey(seed)); }
protected override async Task <IEnumerable <TezosTransaction> > CreatePaymentTxsAsync( Swap swap, int lockTimeSeconds, CancellationToken cancellationToken = default) { Log.Debug("Create payment transactions for swap {@swapId}", swap.Id); var fa12 = Fa12; var fa12Api = fa12.BlockchainApi as ITokenBlockchainApi; var requiredAmountInTokens = AmountHelper.QtyToAmount(swap.Side, swap.Qty, swap.Price, fa12.DigitsMultiplier); var refundTimeStampUtcInSec = new DateTimeOffset(swap.TimeStamp.ToUniversalTime().AddSeconds(lockTimeSeconds)).ToUnixTimeSeconds(); var isInitTx = true; var rewardForRedeemInTokenDigits = swap.IsInitiator ? swap.PartyRewardForRedeem.ToTokenDigits(fa12.DigitsMultiplier) : 0; var unspentAddresses = (await Fa12Account .GetUnspentAddressesAsync(cancellationToken) .ConfigureAwait(false)) .ToList() .SortList(new AvailableBalanceAscending()); var transactions = new List <TezosTransaction>(); foreach (var walletAddress in unspentAddresses) { Log.Debug("Create swap payment tx from address {@address} for swap {@swapId}", walletAddress.Address, swap.Id); var balanceInTz = (await TezosAccount .GetAddressBalanceAsync( address: walletAddress.Address, cancellationToken: cancellationToken) .ConfigureAwait(false)) .Available; var balanceInTokens = (await Fa12Account .GetAddressBalanceAsync( address: walletAddress.Address, cancellationToken: cancellationToken) .ConfigureAwait(false)) .Available; Log.Debug("Available balance: {@balance}", balanceInTokens); var balanceInMtz = balanceInTz.ToMicroTez(); var balanceInTokenDigits = balanceInTokens.ToTokenDigits(fa12.DigitsMultiplier); var isRevealed = await _account .IsRevealedSourceAsync(walletAddress.Address, cancellationToken) .ConfigureAwait(false); var feeAmountInMtz = fa12.ApproveFee * 2 + (isInitTx ? fa12.InitiateFee : fa12.AddFee) + (isRevealed ? 0 : fa12.RevealFee); var storageLimitInMtz = (fa12.ApproveStorageLimit * 2 + (isInitTx ? fa12.InitiateStorageLimit : fa12.AddStorageLimit)) * fa12.StorageFeeMultiplier; if (balanceInMtz - feeAmountInMtz - storageLimitInMtz - Xtz.MicroTezReserve <= 0) { Log.Warning( "Insufficient funds at {@address}. Balance: {@balance}, " + "feeAmount: {@feeAmount}, storageLimit: {@storageLimit}.", walletAddress.Address, balanceInMtz, feeAmountInMtz, storageLimitInMtz); continue; } var amountInTokens = requiredAmountInTokens > 0 ? AmountHelper.DustProofMin(balanceInTokens, requiredAmountInTokens, fa12.DigitsMultiplier, fa12.DustDigitsMultiplier) : 0; if (amountInTokens == 0) { break; } requiredAmountInTokens -= amountInTokens; using var callingAddressPublicKey = new SecureBytes((await Fa12Account.GetAddressAsync(walletAddress.Address) .ConfigureAwait(false)) .PublicKeyBytes()); var allowanceResult = await fa12Api .TryGetTokenAllowanceAsync( holderAddress : walletAddress.Address, spenderAddress : fa12.SwapContractAddress, callingAddress : walletAddress.Address, securePublicKey : callingAddressPublicKey, cancellationToken : cancellationToken) .ConfigureAwait(false); if (allowanceResult.HasError) { Log.Error("Error while getting token allowance for {@address} with code {@code} and description {@description}", walletAddress.Address, allowanceResult.Error.Code, allowanceResult.Error.Description); continue; // todo: maybe add approve 0 } if (allowanceResult.Value > 0) { transactions.Add(new TezosTransaction { Currency = fa12, CreationTime = DateTime.UtcNow, From = walletAddress.Address, To = fa12.TokenContractAddress, Fee = fa12.ApproveFee, GasLimit = fa12.ApproveGasLimit, StorageLimit = fa12.ApproveStorageLimit, Params = ApproveParams(fa12.SwapContractAddress, 0), UseDefaultFee = true, Type = BlockchainTransactionType.TokenApprove }); } transactions.Add(new TezosTransaction { Currency = fa12, CreationTime = DateTime.UtcNow, From = walletAddress.Address, To = fa12.TokenContractAddress, Fee = fa12.ApproveFee, GasLimit = fa12.ApproveGasLimit, StorageLimit = fa12.ApproveStorageLimit, Params = ApproveParams(fa12.SwapContractAddress, amountInTokens.ToTokenDigits(fa12.DigitsMultiplier)), UseDefaultFee = true, Type = BlockchainTransactionType.TokenApprove }); if (isInitTx) { transactions.Add(new TezosTransaction { Currency = fa12, CreationTime = DateTime.UtcNow, From = walletAddress.Address, To = fa12.SwapContractAddress, Fee = feeAmountInMtz, GasLimit = fa12.InitiateGasLimit, StorageLimit = fa12.InitiateStorageLimit, Params = InitParams(swap, fa12.TokenContractAddress, amountInTokens.ToTokenDigits(fa12.DigitsMultiplier), refundTimeStampUtcInSec, (long)rewardForRedeemInTokenDigits), UseDefaultFee = true, Type = BlockchainTransactionType.Output | BlockchainTransactionType.SwapPayment }); } //else //{ // transactions.Add(new TezosTransaction // { // Currency = Xtz, // CreationTime = DateTime.UtcNow, // From = walletAddress.Address, // To = Xtz.SwapContractAddress, // Fee = feeAmountInMtz, // GasLimit = Xtz.AddGasLimit, // StorageLimit = Xtz.AddStorageLimit, // UseDefaultFee = true, // Params = AddParams(swap), // Type = BlockchainTransactionType.Output | BlockchainTransactionType.SwapPayment // }); //} if (isInitTx) { isInitTx = false; } if (requiredAmountInTokens <= 0) { break; } } if (requiredAmountInTokens > 0) { Log.Warning("Insufficient funds (left {@requredAmount}).", requiredAmountInTokens); return(Enumerable.Empty <TezosTransaction>()); } return(transactions); }
public async Task <(bool result, bool isRunSuccess, bool hasReveal)> FillOperationsAsync( SecureBytes securePublicKey, TezosConfig tezosConfig, int headOffset = 0, bool isAlreadyRevealed = false, CancellationToken cancellationToken = default) { using var publicKey = securePublicKey.ToUnsecuredBytes(); var rpc = new Rpc(tezosConfig.RpcNodeUri); var managerKey = await rpc .GetManagerKey(From) .ConfigureAwait(false); var actualHead = await rpc .GetHeader() .ConfigureAwait(false); if (Head == null) { Head = await rpc .GetHeader(headOffset) .ConfigureAwait(false); } Operations = new JArray(); var gas = GasLimit.ToString(CultureInfo.InvariantCulture); var storage = StorageLimit.ToString(CultureInfo.InvariantCulture); var revealed = managerKey.Value <string>() != null || isAlreadyRevealed; UsedCounters = revealed ? 1 : 2; var counter = UseOfflineCounter ? await TezosCounter.Instance .GetOfflineCounterAsync( address : From, head : actualHead["hash"].ToString(), rpcNodeUri : tezosConfig.RpcNodeUri, numberOfCounters : UsedCounters) .ConfigureAwait(false) : await TezosCounter.Instance .GetCounterAsync( address : From, head : actualHead["hash"].ToString(), rpcNodeUri : tezosConfig.RpcNodeUri) .ConfigureAwait(false); if (!revealed) { var revealOp = new JObject { ["kind"] = Internal.OperationType.Reveal, ["fee"] = "0", ["public_key"] = Base58Check.Encode(publicKey, Prefix.Edpk), ["source"] = From, ["storage_limit"] = "0", ["gas_limit"] = tezosConfig.RevealGasLimit.ToString(), ["counter"] = counter.ToString() }; Operations.AddFirst(revealOp); counter++; } var operation = new JObject { ["kind"] = OperationType, ["source"] = From, ["fee"] = ((int)Fee).ToString(CultureInfo.InvariantCulture), ["counter"] = counter.ToString(), ["gas_limit"] = gas, ["storage_limit"] = storage, }; if (OperationType == Internal.OperationType.Transaction) { operation["amount"] = Math.Round(Amount, 0).ToString(CultureInfo.InvariantCulture); operation["destination"] = To; } else if (OperationType == Internal.OperationType.Delegation) { operation["delegate"] = To; } else { throw new NotSupportedException($"Operation type {OperationType} not supporeted yet."); } Operations.Add(operation); if (Params != null) { operation["parameters"] = Params; } var isRunSuccess = false; if (UseRun) { var fill = await rpc .AutoFillOperations(tezosConfig, Head, Operations, UseSafeStorageLimit) .ConfigureAwait(false); if (!fill) { Log.Warning("Operation autofilling error"); } else { Fee = Operations.Last["fee"].Value <decimal>().ToTez(); isRunSuccess = true; } } return( result : true, isRunSuccess : isRunSuccess, hasReveal : !revealed ); }
public BitcoinBasedKey(SecureBytes seed) { using var scopedSeed = seed.ToUnsecuredBytes(); Key = new Key(scopedSeed); }
public abstract IExtKey CreateExtKey(SecureBytes seed, int keyType);
public abstract IKey CreateKey(SecureBytes seed);