public byte[] GetRegistrationTokenBytes(RsaKey rsaKey, BitcoinSecret privateKeyEcdsa) { var token = new List <byte>(); token.AddRange(Encoding.ASCII.GetBytes(ServerId.PadRight(34))); if (Ipv4Addr != null) { token.AddRange(Ipv4Addr.GetAddressBytes()); } else { token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); } if (Ipv6Addr != null) { token.AddRange(Ipv6Addr.GetAddressBytes()); } else { token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); } if (OnionAddress != null) { token.AddRange(Encoding.ASCII.GetBytes(OnionAddress)); } else { token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); token.Add(0x00); } // TODO: Review the use of BitConverter for endian-ness issues byte[] portNumber = BitConverter.GetBytes(Port); token.Add(portNumber[0]); token.Add(portNumber[1]); CryptoUtils cryptoUtils = new CryptoUtils(rsaKey, privateKeyEcdsa); // Sign header (excluding preliminary length marker bytes) with RSA RsaSignature = cryptoUtils.SignDataRSA(token.ToArray()); byte[] rsaLength = BitConverter.GetBytes(RsaSignature.Length); // Sign header (excluding preliminary length marker bytes) with ECDSA EcdsaSignature = cryptoUtils.SignDataECDSA(token.ToArray()); byte[] ecdsaLength = BitConverter.GetBytes(EcdsaSignature.Length); // TODO: Check if the lengths are >2 bytes. Should not happen // for most conceivable signature schemes at current key lengths token.Add(rsaLength[0]); token.Add(rsaLength[1]); token.AddRange(RsaSignature); token.Add(ecdsaLength[0]); token.Add(ecdsaLength[1]); token.AddRange(EcdsaSignature); // Server configuration hash token.AddRange(Encoding.ASCII.GetBytes(ConfigurationHash)); // Finally add protocol byte and computed length to beginning of header byte[] protocolVersionByte = BitConverter.GetBytes(ProtocolVersion); byte[] headerLength = BitConverter.GetBytes(token.Count); token.Insert(0, protocolVersionByte[0]); token.Insert(1, headerLength[0]); token.Insert(2, headerLength[1]); return(token.ToArray()); }