/// <inheritdoc /> public MaskedAuthenticatedMessage Create( MerkleTree tree, int index, TryteString message, Hash nextRoot, TryteString channelKey, Entity.Mode mode, int securityLevel) { var nextRootTrits = nextRoot.ToTrits(); var messageTrits = message.ToTrits(); var indexTrits = Pascal.Encode(index); var messageLengthTrits = Pascal.Encode(messageTrits.Length); var subtree = tree.GetSubtreeByIndex(index); this.Curl.Reset(); this.Curl.Absorb(channelKey.ToTrits()); this.Curl.Absorb(tree.Root.Hash.ToTrits()); var payload = new List <int>(); payload.InsertRange(0, indexTrits); payload.InsertRange(indexTrits.Length, messageLengthTrits); var nextRootStart = indexTrits.Length + messageLengthTrits.Length; this.Curl.Absorb(payload.Take(nextRootStart).ToArray()); // encrypt next root together with message trits payload.InsertRange(nextRootStart, this.Mask.Mask(nextRootTrits.Concat(messageTrits).ToArray(), this.Curl)); // calculate message end and add nonce var messageEnd = nextRootStart + nextRootTrits.Length + messageTrits.Length; this.AddNonce(securityLevel, messageEnd, payload); // create signature, encrypt signature + sibling count (get trits from pascal) + siblings var signature = this.SigningHelper.Signature(this.Curl.Rate(Constants.TritHashLength), subtree.Key.ToTrits()); var subtreeTrits = subtree.ToTryteString().ToTrits(); var siblingsCount = subtreeTrits.Length / Constants.TritHashLength; var encryptedSignature = this.Mask.Mask(signature.Concat(Pascal.Encode(siblingsCount)).Concat(subtreeTrits).ToArray(), this.Curl); // insert signature and pad to correct length (% 3 == 0) payload.InsertRange(messageEnd + NonceLength, encryptedSignature); PadPayload(payload); this.Curl.Reset(); var messageAddress = this.GetMessageAddress(tree.Root.Hash, mode); return(new MaskedAuthenticatedMessage { Payload = CreateBundleFromPayload(messageAddress, payload), Root = tree.Root.Hash, Address = messageAddress, NextRoot = nextRoot }); }
/// <summary> /// The get message address. /// </summary> /// <param name="rootHash"> /// The root Hash. /// </param> /// <param name="mode"> /// The mode. /// </param> /// <returns> /// The <see cref="Address"/>. /// </returns> private Address GetMessageAddress(TryteString rootHash, Entity.Mode mode) { if (mode == Entity.Mode.Public) { return(new Address(rootHash.Value)); } var addressHash = this.Mask.Hash(rootHash); return(new Address(addressHash.Value)); }