Пример #1
0
        /// <summary>
        /// Computes a cryptographically secure random Kademlia key that matches the boundaries of this <see cref="IBucket"/>.
        /// </summary>
        /// <returns></returns>
        public static string GetRandomKey(string key, int index)
        {
            byte[] keyBytes = EncryptionProvider.GetBytes(key);
            byte[] bytes    = GetRandomKey();

            int sharedPrefixLengthBytes = (int)Math.Floor((index / (decimal)8));
            int sharedPrefixLengthBits  = index % 8;

            CryptoRandom cryptoRandom = new CryptoRandom();

            for (int i = 0; i < keyBytes.Length; i++)
            {
                if (i > sharedPrefixLengthBytes)
                {
                    // Keep randomness
                    bytes[i] = (byte)(bytes[i] ^ keyBytes[i]);
                }
                else if (i < sharedPrefixLengthBytes)
                {
                    // Use the bytes from the given key
                    bytes[i] = keyBytes[i];
                }
                else if (i == sharedPrefixLengthBytes)
                {
                    // Preserve some random bits without modifying the most significant bit index
                    int min   = (255 >> (sharedPrefixLengthBits + 1)) + 1;
                    int max   = (255 >> sharedPrefixLengthBits) + 1;
                    int shift = cryptoRandom.Next(min, max);
                    bytes[i] = (byte)(shift ^ keyBytes[i]);
                }
            }
            return(EncryptionProvider.GetString(bytes));
        }
Пример #2
0
        /// <summary>
        /// Computes the distance between the specified node ids.
        /// </summary>
        /// <param name="nodeId1"></param>
        /// <param name="nodeId2"></param>
        /// <returns></returns>
        internal static byte[] DistanceBytes(string nodeId1, string nodeId2)
        {
            if (string.IsNullOrEmpty(nodeId1))
            {
                throw new ArgumentNullException("nodeId1");
            }

            if (string.IsNullOrEmpty(nodeId2))
            {
                throw new ArgumentNullException("nodeId2");
            }

            if (nodeId1.Length != nodeId2.Length)
            {
                throw new ArgumentException("The specified node ids must be of equal length");
            }

            byte[] nodeId1Bytes = EncryptionProvider.GetBytes(nodeId1);
            byte[] nodeId2Bytes = EncryptionProvider.GetBytes(nodeId2);

            // Compute XOR
            byte[] distance = new byte[nodeId1Bytes.Length];
            for (int i = distance.Length - 1; i >= 0; i--)
            {
                distance[i] = (byte)(nodeId1Bytes[i] ^ nodeId2Bytes[i]);
            }

            return(distance);
        }