private void RemoteTimestamp(BlockchainProof proof)
        {
            var uri = _configuration.RemoteServer();

            uri = uri.Append($"/api/timestamp/{proof.MerkleRoot.ConvertToBase64()}");

            using (var client = new WebClient())
            {
                var json = client.DownloadString(uri);
                if (!string.IsNullOrEmpty(json))
                {
                    var timestamp = JsonConvert.DeserializeObject <Timestamp>(json);
                    if (timestamp.Proof != null)
                    {
                        if (timestamp.Proof.Confirmations > 0)
                        {
                            proof.Receipt       = ByteExtensions.Combine(timestamp.Path, timestamp.Proof.Receipt);
                            proof.Address       = timestamp.Proof.Address;
                            proof.Confirmations = timestamp.Proof.Confirmations;
                            proof.Blockchain    = timestamp.Proof.Blockchain;
                        }
                    }
                }
            }
        }
Beispiel #2
0
        public static byte[] Encode(List <NetworkAddress> addresses)
        {
            List <byte[]> addressData = new List <byte[]>();

            foreach (var address in addresses)
            {
                switch (address.Type)
                {
                case AddressType.IpV4:
                    addressData.Add(EncodeIpV4(address));
                    break;

                case AddressType.IpV6:
                    addressData.Add(EncodeIpV6(address));
                    break;
// TODO: support TOR
//                    case AddressType.TorV2:
//                        byte[] torv2 = new byte[12];
//                        torv2[0] = 2;
//                        break;
//                    case AddressType.TorV3:
//                        byte[] torv3 = new byte[37];
//                        torv3[0] = 3;
//                        addressData.Add(torv3);
//                        break;
                }
            }

            return(ByteExtensions.Combine(addressData.ToArray()));
        }
Beispiel #3
0
        public byte[] GetBytes()
        {
            var properties   = GetProperties();
            var propertyData = new List <byte[]>();
            int index        = 0;

            ValidateProperties(properties);

            propertyData.Add(_messageDefinition.TypeId.GetBytesBigEndian());

            foreach (var property in properties)
            {
                var definition = _messageDefinition.Properties[index];
                if (definition.Type.VariableLength)
                {
                    ushort length = (ushort)((ushort)property.Length / definition.Type.LengthPerProperty);
                    propertyData.Add(ByteExtensions.Combine(length.GetBytesBigEndian(), property));
                }
                else
                {
                    if (property.Length != definition.Type.Length)
                    {
                        throw new ArgumentException("wrong property size");
                    }

                    propertyData.Add(property);
                }

                index++;
            }

            return(ByteExtensions.Combine(propertyData.ToArray()));
        }
Beispiel #4
0
        public byte[] GetDataWithRealmAndHmac(byte[] nextHmac)
        {
            if (ShortChannelId.Length != 8)
            {
                throw new ArgumentException("invalid property size.", nameof(ShortChannelId));
            }

            if (Padding.Length != 12)
            {
                throw new ArgumentException("invalid property size.", nameof(Padding));
            }

            if (nextHmac.Length != 32)
            {
                throw new ArgumentException("invalid property size.", nameof(nextHmac));
            }

            return(ByteExtensions.Combine(
                       new[] { Realm },
                       ShortChannelId,
                       AmountToForward.GetBytesBigEndian(),
                       OutgoingCltvValue.GetBytesBigEndian(),
                       Padding,
                       nextHmac));
        }
Beispiel #5
0
 public override List <byte[]> GetProperties()
 {
     return(new List <byte[]>
     {
         ChannelId,
         Signature,
         ByteExtensions.Combine(HtlcSignatures.ToArray())
     });
 }
Beispiel #6
0
 public byte[] GetData()
 {
     return(ByteExtensions.Combine(
                Hmac,
                ((ushort)FailureMessageData.Length).GetBytesBigEndian(),
                FailureMessageData,
                ((ushort)Pad.Length).GetBytesBigEndian(),
                Pad));
 }
Beispiel #7
0
        public static (byte[] plainText, byte[] mac) DecryptWithAdditionalData(byte[] key, byte[] nonce, byte[] additionalData, byte[] cipherText)
        {
            var polyKey = ChaCha20Encrypt(new byte[32], key, nonce);
            var data    = ByteExtensions.Combine(additionalData, Pad16(additionalData),
                                                 cipherText, Pad16(cipherText),
                                                 BitConverter.GetBytes((long)additionalData.Length),
                                                 BitConverter.GetBytes((long)cipherText.Length));

            var mac       = CalculateMac(polyKey, data);
            var plainText = ChaCha20Decrypt(cipherText, key, nonce, true);

            return(plainText, mac);
        }
        public byte[] Encode(List <byte[]> shortIdsToEncode, bool compress)
        {
            var data = ByteExtensions.Combine(shortIdsToEncode.ToArray());

            if (compress)
            {
                ZLibCompression zLibCompression = new ZLibCompression();
                var             compressed      = zLibCompression.Compress(data);
                return(ByteExtensions.Combine(new byte[] { 1 }, compressed));
            }

            return(ByteExtensions.Combine(new byte[] { 0 }, data));
        }
Beispiel #9
0
        public static (byte[], byte[]) EncryptWithAdditionalData(byte[] key, byte[] nonce, byte[] additionalData,
                                                                 byte[] plaintext, bool skipFirst64Byte = true)
        {
            var polyKey    = ChaCha20Encrypt(new byte[32], key, nonce);
            var cipherText = ChaCha20Encrypt(plaintext, key, nonce, skipFirst64Byte);
            var data       = ByteExtensions.Combine(additionalData, Pad16(additionalData),
                                                    cipherText, Pad16(cipherText),
                                                    BitConverter.GetBytes((long)additionalData.Length),
                                                    BitConverter.GetBytes((long)cipherText.Length));

            var macTag = CalculateMac(polyKey, data);

            return(cipherText, macTag);
        }
Beispiel #10
0
        public byte[] ApplyActOne(ECKeyPair ephemeralKeyPair = null)
        {
            if (_state.HandshakeState != HandshakeState.Initialized)
            {
                throw new InvalidOperationException($"Invalid handshake state {_state.HandshakeState}. Must be Initialized");
            }

            _state.EphemeralKeyPair = ephemeralKeyPair ?? Secp256K1.GenerateKeyPair();
            byte[] handshakeHash = SHA256.ComputeHash(_state.HandshakeHash.ConcatToNewArray(_state.EphemeralKeyPair.PublicKeyCompressed));
            byte[] ss            = ECDH.ComputeHashedPoint(_state.RemoteAddress.PublicKey.PublicKeyParameters, _state.EphemeralKeyPair.PrivateKey);
            (byte[] chainingKey, byte[] tempK1) = HmacSha256.ComputeHashes(_state.ChainingKey, ss);
            _state.ChainingKey = chainingKey;
            (_, byte[] tag)    = ChaCha20Poly1305.EncryptWithAdditionalData(tempK1, _state.SendNonce.GetBytes(), handshakeHash, new byte[0]);
            handshakeHash      = SHA256.ComputeHash(handshakeHash.ConcatToNewArray(tag));

            _state.HandshakeHash  = handshakeHash;
            _state.HandshakeState = HandshakeState.Act1;
            return(ByteExtensions.Combine(new byte[] { 0 }, _state.EphemeralKeyPair.PublicKeyCompressed, tag));
        }
Beispiel #11
0
        public byte[] ApplyActTwo(ECKeyPair initiatorEphemeralKey, ECKeyPair localEphemeralKey = null)
        {
            if (_state.HandshakeState != HandshakeState.Act1)
            {
                throw new InvalidOperationException($"Invalid Handshake state {_state.HandshakeState}. Must be Act1");
            }

            _state.EphemeralKeyPair = localEphemeralKey ?? Secp256K1.GenerateKeyPair();
            byte[] handshakeHash = SHA256.ComputeHash(_state.HandshakeHash.ConcatToNewArray(_state.EphemeralKeyPair.PublicKeyCompressed));
            byte[] ss            = ECDH.ComputeHashedPoint(initiatorEphemeralKey.PublicKeyParameters, _state.EphemeralKeyPair.PrivateKey);
            (byte[] chainingKey, byte[] tempK2) = HmacSha256.ComputeHashes(_state.ChainingKey, ss);
            (_, byte[] tag1) = ChaCha20Poly1305.EncryptWithAdditionalData(tempK2, new byte[12], handshakeHash, new byte[0]);
            handshakeHash    = SHA256.ComputeHash(handshakeHash.ConcatToNewArray(tag1));

            _state.HandshakeHash  = handshakeHash;
            _state.ChainingKey    = chainingKey;
            _state.TempKey2       = tempK2;
            _state.HandshakeState = HandshakeState.Act2;
            return(ByteExtensions.Combine(new byte[] { 0 }, _state.EphemeralKeyPair.PublicKeyCompressed, tag1));
        }
Beispiel #12
0
        /// <summary>
        /// Loads the embedded album art from the item with the given path.
        /// MPD usually implements this by reading embedded pictures from binary tags (e.g. ID3v2’s APIC tag).
        /// Uses <see cref="Commands.Database.ReadPicture"/> recursively under the hood to get the full image and returns the image content as a byte array.
        /// Returns null if the file can't be found or contains no image.
        /// </summary>
        /// <param name="path">path to an item</param>
        /// <returns>AlbumArt with byte[] image or null</returns>
        public async Task <IAlbumArt> LoadEmbeddedAlbumArt(string path)
        {
            var       completed = false;
            var       offset    = 0;
            var       array     = new byte[0];
            IAlbumArt art       = null;

            while (!completed)
            {
                var result = await SendAsync(new Commands.Database.ReadPicture(path, offset));

                if (result.Result != null && !result.Status.HasError)
                {
                    if (result.Result.ChunkLength == 0)
                    {
                        completed = true;
                        art       = new AlbumArt
                        {
                            Bytes    = array,
                            ItemPath = path,
                            MimeType = result.Result.MimeType
                        };
                    }
                    else
                    {
                        offset += result.Result.ChunkLength;
                        array   = ByteExtensions.Combine(array, result.Result.Binary);
                    }
                }
                else
                {
                    completed = true;
                }
            }

            return(art.HasContent ? art : null);
        }
Beispiel #13
0
        public byte[] Build(byte[] messageData)
        {
            if (messageData.Length > 65535)
            {
                throw new MessageException("Message size exceeds maximum size.");
            }

            (byte[] encryptedLength, byte[] lengthMac) = ChaCha20Poly1305.EncryptWithAdditionalData(_transportState.SendEncryptionKey,
                                                                                                    _transportState.SendNonce.GetBytes(), new byte[0], ((ushort)messageData.Length).GetBytesBigEndian());

            _transportState.SendNonce.Increment();

            (byte[] encryptedMessage, byte[] messageMac) = ChaCha20Poly1305.EncryptWithAdditionalData(_transportState.SendEncryptionKey,
                                                                                                      _transportState.SendNonce.GetBytes(), new byte[0], messageData);

            _transportState.SendNonce.Increment();

            if (_transportState.SendNonce.Value == 1000)
            {
                _transportState.RotateSendKey();
            }

            return(ByteExtensions.Combine(encryptedLength, lengthMac, encryptedMessage, messageMac));
        }
Beispiel #14
0
        public byte[] ApplyActThree(byte[] tempK2, ECKeyPair responderEphemeralKey)
        {
            if (_state.HandshakeState != HandshakeState.Act2)
            {
                throw new InvalidOperationException($"Invalid Handshake state {_state.HandshakeState}. Must be Act2");
            }

            (byte[] cipherText, byte[] tag) = ChaCha20Poly1305.EncryptWithAdditionalData(tempK2, _state.SendNonce.GetBytes(), _state.HandshakeHash, _state.LocalKeyPair.PublicKeyCompressed);
            byte[] cipherAndMac  = cipherText.ConcatToNewArray(tag);
            byte[] handshakeHash = SHA256.ComputeHash(_state.HandshakeHash.ConcatToNewArray(cipherAndMac));
            byte[] ss            = ECDH.ComputeHashedPoint(responderEphemeralKey.PublicKeyParameters, _state.LocalKeyPair.PrivateKey);
            (byte[] chainingKey, byte[] tempK3) = HmacSha256.ComputeHashes(_state.ChainingKey, ss);
            (_, byte[] tag2) = ChaCha20Poly1305.EncryptWithAdditionalData(tempK3, new byte[12], handshakeHash, new byte[0]);
            (byte[] encryptKey, byte[] decryptKey) = HmacSha256.ComputeHashes(chainingKey, new byte[0]);

            _state.HandshakeHash        = handshakeHash;
            _state.ChainingKey          = chainingKey;
            _state.SendEncryptionKey    = encryptKey;
            _state.ReceiveDecryptionKey = decryptKey;
            _state.SendNonce.Reset();
            _state.ReceiveNonce.Reset();
            _state.HandshakeState = HandshakeState.Finished;
            return(ByteExtensions.Combine(new byte[] { 0 }, cipherAndMac, tag2));
        }
Beispiel #15
0
        /*
         *  Implementation of
         *  https://github.com/lightningnetwork/lightning-rfc/blob/master/04-onion-routing.md#packet-construction
         */
        public OnionPacket Build()
        {
            var           hopsCount        = HopsData.Count;
            List <byte[]> hopSharedSecrets = new List <byte[]>();

            var ephemeralKey  = SessionKey.PrivateKey.D;
            var ephemeralKeys = new List <BigInteger>();

            for (var i = 0; i < hopsCount; i++)
            {
                ephemeralKeys.Add(ephemeralKey);

                // Perform ECDH and hash the result.
                var ecdhResult      = HopsData[i].PublicKey.PublicKeyParameters.Q.Multiply(ephemeralKey);
                var hopSharedSecret = SHA256.ComputeHash(ecdhResult.GetEncoded());
                hopSharedSecrets.Add(hopSharedSecret);

                // Derive ephemeral public key from private key.
                ECKeyPair ephemeralKeyPair = new ECKeyPair(ephemeralKey.ToByteArrayUnsigned(), true);

                // Compute blinding factor.
                var combined = ephemeralKeyPair.PublicKeyCompressed.ConcatToNewArray(hopSharedSecret);

                BigInteger blindingFactor = new BigInteger(1, SHA256.ComputeHash(combined));

                // Blind ephemeral key for next hop.
                ephemeralKey = ephemeralKey.Multiply(blindingFactor);
                ephemeralKey = ephemeralKey.Mod(ECKeyPair.Secp256K1.N);
            }

            // Generate the padding, called "filler strings" in the paper.
            var filler = GenerateFiller(Rho, hopsCount, HopDataSize, hopSharedSecrets);

            // Allocate and initialize fields to zero-filled slices
            var routingInfoSize = HopDataSize * HopsMaximumCount;
            var routingInfo     = new byte[routingInfoSize];
            var nextHmac        = new byte[HmacSize];

            // Compute the routing information for each hop along with a
            // MAC of the routing information using the shared key for that hop.
            for (int i = hopsCount - 1; i >= 0; i--)
            {
                var rhoKey = GenerateKey(Rho, hopSharedSecrets[i]);
                var muKey  = GenerateKey(Mu, hopSharedSecrets[i]);

                var perHopData  = HopsData[i].GetDataWithRealmAndHmac(nextHmac);
                var streamBytes = GenerateCipherStream(rhoKey, (uint)routingInfoSize);

                // Shift right
                Array.Copy(routingInfo, 0, routingInfo, HopDataSize, routingInfo.Length - HopDataSize);
                // Add per hop data
                Array.Copy(perHopData, 0, routingInfo, 0, perHopData.Length);

                routingInfo = Xor(routingInfo, streamBytes);

                if (i == hopsCount - 1)
                {
                    Array.Copy(filler, 0, routingInfo, routingInfo.Length - filler.Length, filler.Length);
                }

                var packet = routingInfo.ConcatToNewArray(AssociatedData);
                nextHmac = CalculateMac(muKey, packet);
            }

            byte version = 0x0;
            var  data    = ByteExtensions.Combine(new byte[] { version }, SessionKey.PublicKeyCompressed, routingInfo, nextHmac);

            return(new OnionPacket(SessionKey, nextHmac, HopsData, version, data));
        }
Beispiel #16
0
 public byte[] GetBytes() => ByteExtensions.Combine(BitConverter.GetBytes(0), BitConverter.GetBytes(_value));