/// <summary> /// /// </summary> /// <param name="seed"></param> /// <param name="security"></param> /// <param name="index"></param> /// <param name="checksum"></param> /// <param name="curl"></param> /// <returns></returns> public static string NewAddress(string seed, int security, int index, bool checksum, ICurl curl) { if (!InputValidator.IsValidSecurityLevel(security)) { throw new ArgumentException(Constants.INVALID_SECURITY_LEVEL_INPUT_ERROR); } Signing signing = new Signing(curl); sbyte[] key = signing.Key(Converter.ToTrits(seed), index, security); sbyte[] digests = signing.Digests(key); sbyte[] addressTrits = signing.Address(digests); string address = Converter.ToTrytes(addressTrits); if (checksum) { address = address.AddChecksum(); } return(address); }
internal static List <string> SignInputsAndReturn(string seed, List <Input> inputs, Bundle bundle, List <string> signatureFragments, ICurl curl) { bundle.FinalizeBundle(curl); bundle.AddTrytes(signatureFragments); // SIGNING OF INPUTS // // Here we do the actual signing of the inputs // Iterate over all bundle transactions, find the inputs // Get the corresponding private key and calculate the signatureFragment for (int i = 0; i < bundle.Transactions.Count; i++) { if (bundle.Transactions[i].Value < 0) { string thisAddress = bundle.Transactions[i].Address; // Get the corresponding keyIndex of the address int keyIndex = 0; int keySecurity = 0; foreach (Input input in inputs) { if (input.Address.StartsWith(thisAddress, StringComparison.Ordinal)) { keyIndex = input.KeyIndex; keySecurity = input.Security; break; } } string bundleHash = bundle.Transactions[i].Bundle; // Get corresponding private key of address sbyte[] key = new Signing(curl).Key(Converter.ToTrits(seed), keyIndex, keySecurity); // First 6561 trits for the firstFragment //sbyte[] firstFragment = ArrayUtils.SubArray2(key, 0, 6561); // Get the normalized bundle hash sbyte[] normalizedBundleHash = bundle.NormalizedBundle(bundleHash); // First bundle fragment uses 27 trytes //sbyte[] firstBundleFragment = ArrayUtils.SubArray2(normalizedBundleHash, 0, 27); // Calculate the new signatureFragment with the first bundle fragment //sbyte[] firstSignedFragment = // new Signing(curl).SignatureFragment(firstBundleFragment, firstFragment); // Convert signature to trytes and assign the new signatureFragment //bundle.Transactions[i].SignatureMessageFragment = Converter.ToTrytes(firstSignedFragment); // if user chooses higher than 27-tryte security // for each security level, add an additional signature for (int j = 0; j < keySecurity; j++) { int hashPart = j % 3; // Add parts of signature for bundles with same address if (bundle.Transactions[i + j].Address.StartsWith(thisAddress, StringComparison.Ordinal)) { // Use 6562 trits starting from j*6561 sbyte[] keyFragment = ArrayUtils.SubArray2(key, 6561 * j, 6561); // The current part of the bundle hash sbyte[] bundleFragment = ArrayUtils.SubArray2(normalizedBundleHash, 27 * hashPart, 27); // Calculate the new signature sbyte[] signedFragment = new Signing(curl).SignatureFragment(bundleFragment, keyFragment); // Convert signature to trytes and assign it again to this bundle entry bundle.Transactions[i + j].SignatureMessageFragment = (Converter.ToTrytes(signedFragment)); } } } } List <string> bundleTrytes = new List <string>(); // Convert all bundle entries into trytes foreach (Transaction tx in bundle.Transactions) { bundleTrytes.Add(tx.ToTrytes()); } bundleTrytes.Reverse(); return(bundleTrytes); }
/// <summary> /// </summary> /// <param name="curl"></param> public Multisig(ICurl curl) { _curl = curl; _curl.Reset(); _signing = new Signing(); }
/// <summary> /// /// </summary> /// <param name="bundle"></param> /// <param name="curl"></param> /// <returns></returns> public static bool IsBundle(Bundle bundle, ICurl curl = null) { if (curl == null) { curl = SpongeFactory.Create(SpongeFactory.Mode.KERL); } long totalSum = 0; int lastIndex = bundle.Length - 1; for (int i = 0; i < bundle.Length; i++) { var tx = bundle.Transactions[i]; totalSum += tx.Value; if (tx.CurrentIndex != i) { throw new ArgumentException(Constants.INVALID_BUNDLE_ERROR); } if (tx.LastIndex != lastIndex) { throw new ArgumentException(Constants.INVALID_BUNDLE_ERROR); } sbyte[] txTrits = Converter.ToTrits(tx.ToTrytes().Substring(2187, 162)); curl.Absorb(txTrits); // continue if output or signature tx if (tx.Value >= 0) { continue; } // here we have an input transaction (negative value) List <string> fragments = new List <string> { tx.SignatureMessageFragment }; // find the subsequent txs containing the remaining signature // message fragments for this input transaction for (int j = i; j < bundle.Length - 1; j++) { Transaction tx2 = bundle.Transactions[j + 1]; // check if the tx is part of the input transaction if (tx.Address.Equals(tx2.Address, StringComparison.Ordinal) && tx2.Value == 0) { // append the signature message fragment fragments.Add(tx2.SignatureMessageFragment); } } bool valid = new Signing(curl.Clone()).ValidateSignatures(tx.Address, fragments.ToArray(), tx.Bundle); if (!valid) { throw new ArgumentException(Constants.INVALID_SIGNATURES_ERROR); } } // sum of all transaction must be 0 if (totalSum != 0) { throw new ArgumentException(Constants.INVALID_BUNDLE_SUM_ERROR); } sbyte[] bundleHashTrits = new sbyte[Sponge.HASH_LENGTH]; curl.Squeeze(bundleHashTrits, 0, Sponge.HASH_LENGTH); string bundleHash = Converter.ToTrytes(bundleHashTrits); if (!bundleHash.Equals(bundle.Transactions[0].Bundle, StringComparison.Ordinal)) { throw new ArgumentException(Constants.INVALID_BUNDLE_HASH_ERROR); } return(true); }