/// <summary> /// </summary> /// <param name="payload"></param> /// <param name="sideKey"></param> /// <param name="root"></param> /// <returns>(message,nextRoot)</returns> public Tuple <string, string> DecodeMessage(string payload, string sideKey, string root) { if (string.IsNullOrEmpty(sideKey)) { sideKey = "999999999999999999999999999999999999999999999999999999999999999999999999999999999"; } var payloadTrits = Converter.ToTrits(payload); var sideKeyTrits = Converter.ToTrits(sideKey); var rootTrits = Converter.ToTrits(root); ICurl curl = new Curl(SpongeFactory.Mode.CURLP27); // parse var result = Pascal.Decode(payloadTrits); var index = (int)result.Item1; var indexEnd = result.Item2; var tempTrits = new sbyte[payloadTrits.Length - indexEnd]; Array.Copy(payloadTrits, indexEnd, tempTrits, 0, tempTrits.Length); result = Pascal.Decode(tempTrits); var messageLength = (int)result.Item1; var messageLengthEnd = result.Item2; var nextRootStart = indexEnd + messageLengthEnd; var messageStart = nextRootStart + Constants.HashLength; var messageEnd = messageStart + messageLength; curl.Absorb(sideKeyTrits); curl.Absorb(rootTrits); if (messageLength > payloadTrits.Length) { throw new ArgumentOutOfRangeException(); } curl.Absorb(payloadTrits, 0, nextRootStart); MaskHelper.UnMaskSlice(payloadTrits, nextRootStart, messageStart - nextRootStart, curl); MaskHelper.UnMaskSlice(payloadTrits, messageStart, messageEnd - messageStart, curl); var pos = messageEnd; MaskHelper.UnMaskSlice(payloadTrits, pos, Constants.MessageNonceLength, curl); pos += Constants.HashLength / 3; var hmac = new sbyte[Constants.HashLength]; Array.Copy(curl.Rate, hmac, Constants.HashLength); var security = HashHelper.CheckSumSecurity(hmac); MaskHelper.UnMaskSlice(payloadTrits, pos, payloadTrits.Length - pos, curl); if (security == 0) { // InvalidHash curl.Reset(); throw new ApplicationException(); } var sigEnd = pos + security * Constants.KeyLength; HashHelper.DigestBundleSignature(hmac, payloadTrits, pos, sigEnd - pos, curl); Array.Copy(curl.Rate, hmac, Constants.HashLength); curl.Reset(); pos = sigEnd; tempTrits = new sbyte[payloadTrits.Length - pos]; Array.Copy(payloadTrits, pos, tempTrits, 0, tempTrits.Length); result = Pascal.Decode(tempTrits); curl.Absorb(hmac); if (result.Item1 != 0) { // get address lite Array.Copy(curl.Rate, hmac, Constants.HashLength); pos += result.Item2; var sibEnd = pos + (int)result.Item1; var siblings = new sbyte[sibEnd - pos]; Array.Copy(payloadTrits, pos, siblings, 0, siblings.Length); curl.Reset(); MerkleTree.Root(hmac, siblings, index, curl); } if (!curl.Rate.SequenceEqual(rootTrits)) { // InvalidSignature curl.Reset(); throw new ApplicationException(); } var message = Converter.ToTrytes(payloadTrits, messageStart, messageLength); var nextRoot = Converter.ToTrytes(payloadTrits, nextRootStart, Constants.HashLength); return(new Tuple <string, string>(message, nextRoot)); }
private sbyte[] CreateMaskedPayload( sbyte[] seedTrits, sbyte[] messageTrits, sbyte[] keyTrits, sbyte[] rootTrits, sbyte[] siblingsTrits, sbyte[] nextRootTrits, int start, int index, int security) { ICurl curl = new Curl(SpongeFactory.Mode.CURLP27); ICurl encrCurl = new Curl(SpongeFactory.Mode.CURLP27); var hammingNonce = new HammingNonce(SpongeFactory.Mode.CURLP27); var minLength = GetPayloadMinLength(messageTrits.Length, siblingsTrits.Length, index, security); var payloadLength = (int)TritsHelper.RoundThird(minLength); var payload = new sbyte[payloadLength]; // Creates a signed, encrypted payload from a message // generate the key and the get the merkle tree hashes var messageLength = messageTrits.Length; var indexP = Pascal.EncodedLength(index); var messageP = Pascal.EncodedLength(messageLength); var siblingsLength = siblingsTrits.Length; var siblingsCount = siblingsTrits.Length / Constants.HashLength; var siblingsPascalLength = Pascal.EncodedLength(siblingsCount); var signatureLength = security * Constants.KeyLength; var nextRootStart = indexP + messageP; var nextEnd = nextRootStart + nextRootTrits.Length; var messageEnd = nextRootStart + Constants.HashLength + messageLength; var nonceEnd = messageEnd + Constants.MessageNonceLength; var signatureEnd = nonceEnd + signatureLength; var siblingsPascalEnd = signatureEnd + siblingsPascalLength; var siblingsEnd = siblingsPascalEnd + siblingsLength; encrCurl.Absorb(keyTrits); encrCurl.Absorb(rootTrits); var trits = new sbyte[indexP]; Pascal.Encode(index, trits); Array.Copy(trits, 0, payload, 0, indexP); trits = new sbyte[messageP]; Pascal.Encode(messageLength, trits); Array.Copy(trits, 0, payload, indexP, messageP); encrCurl.Absorb(payload, 0, nextRootStart); Array.Copy(nextRootTrits, 0, payload, nextRootStart, nextRootTrits.Length); Array.Copy(messageTrits, 0, payload, nextEnd, messageTrits.Length); MaskHelper.MaskSlice(payload, nextRootStart, messageEnd - nextRootStart, encrCurl); Array.Copy(encrCurl.State, curl.State, encrCurl.State.Length); hammingNonce.Search(security, 0, Constants.HashLength / 3, curl); Array.Copy(curl.State, 0, payload, messageEnd, Constants.MessageNonceLength); MaskHelper.MaskSlice(payload, messageEnd, nonceEnd - messageEnd, encrCurl); curl.Reset(); var subseed = HashHelper.Subseed(seedTrits, start + index, curl); Array.Copy(subseed, 0, payload, nonceEnd, subseed.Length); curl.Reset(); HashHelper.Key(payload, nonceEnd, signatureEnd - nonceEnd, security, curl); curl.Reset(); HashHelper.Signature(encrCurl.Rate, payload, nonceEnd, signatureEnd - nonceEnd, curl); curl.Reset(); trits = new sbyte[siblingsPascalLength]; Pascal.Encode(siblingsCount, trits); Array.Copy(trits, 0, payload, signatureEnd, siblingsPascalLength); Array.Copy(siblingsTrits, 0, payload, siblingsPascalEnd, siblingsLength); MaskHelper.MaskSlice(payload, nonceEnd, siblingsEnd - nonceEnd, encrCurl); encrCurl.Reset(); return(payload); }