예제 #1
0
        /// <summary>
        /// Initializes the state of Key Pair assuming the given Passphrase includes a higher then 100-bit
        /// entropy score using ZXCVBN analysis.  Returns false if the Passphrase does not pass this test, and the
        /// object is not initialized as a result.  Returns true with the Key Pair is ready for use.
        /// </summary>
        /// <param name="EMail"></param>
        /// <param name="Passphrase"></param>
        /// <returns>true if OK/Initialized, false if BAD PASSPHRASE</returns>
        public bool Initialize(string EMail, string Passphrase)
        {
            if (string.IsNullOrWhiteSpace(EMail))
            {
                throw new ArgumentNullException("EMail");
            }
            if (string.IsNullOrWhiteSpace(Passphrase))
            {
                throw new ArgumentNullException("Passphrase");
            }
            if ((int)ScorePotentialPassphrase(Passphrase).Entropy < 100)
            {
                return(false);
            }

            byte[] mangledPWD = Blake2S.ComputeHash(new UTF8Encoding().GetBytes(Passphrase.Trim()));
            _Secret         = SCrypt.ComputeDerivedKey(mangledPWD, new UTF8Encoding().GetBytes(EMail.Trim()), 131072, 8, 1, 1, 32);
            _SecretChecksum = ComputeChecksum(_Secret);

            _PublicID = GeneratePublicIDFromSecret(_Secret, out _PublicChecksum);
            //PROTECT MEMORY AFTER LAST USE OF _Secret
            ProtectedMemory.Protect(_Secret, MemoryProtectionScope.SameProcess);
            _Public = GetBytesFromPublicKey(_PublicID);
            return(true);
        }
예제 #2
0
 protected BLAKE2S(int bits)
     : base(GetHashType(bits), GetName(bits), bits / 8)
 {
     _factory = () =>
     {
         var algo = new Blake2S(bits);
         algo.Initialize();
         return(algo);
     };
 }
예제 #3
0
        /// <summary>
        ///     Encode a publicKey into miniLock format.
        /// </summary>
        /// <param name="publicKey">A 32 byte publicKey.</param>
        /// <exception cref="Sodium.Exceptions.KeyOutOfRangeException"></exception>
        /// <returns>A Base58 encoded publicKey.</returns>
        public static string EncodeMiniLockPublicKey(byte[] publicKey)
        {
            if (publicKey == null || publicKey.Length != PublicKeyBytes)
            {
                throw new KeyOutOfRangeException("publicKey", (publicKey == null) ? 0 : publicKey.Length,
                                                 string.Format("key must be {0} bytes in length.", PublicKeyBytes));
            }

            var final = ArrayHelper.ConcatArrays(publicKey, Blake2S.Hash(publicKey, (byte[])null, 1));

            return(Base58CheckEncoding.EncodePlain(final));
        }
예제 #4
0
 internal static byte ComputeChecksum(byte[] key)
 {
     if (key == null || (key.Length != 32 && key.Length != 33))
     {
         throw new ArgumentOutOfRangeException("key must be 32 or 33 bytes");
     }
     return(Blake2S.ComputeHash(
                key, 0, 32,
                new Blake2sConfig()
     {
         OutputSizeInBytes = 1
     })[0]);
 }
예제 #5
0
        private Blake2S[] DeepCloneBlake2SInstances(Blake2S[] leafHashes)
        {
            if (leafHashes == null)
            {
                return(null);
            }
            var result = new Blake2S[leafHashes.Length];

            for (var idx = 0; idx < _leafHashes.Length; idx++)
            {
                result[idx] = _leafHashes[idx].CloneInternal();
            }

            return(result);
        }
예제 #6
0
        internal Blake2SP(int hashSize, byte[] key)
            : base(hashSize, BlockSizeInBytes)
        {
            if (key == null)
            {
                throw new ArgumentNullException(nameof(key));
            }

            _key        = ArrayUtils.Clone(key);
            _leafHashes = new Blake2S[ParallelismDegree];
            _buffer     = new byte[ParallelismDegree * BlockSizeInBytes];
            _rootHash   = Blake2SPCreateRoot();
            for (var idx = 0; idx < ParallelismDegree; idx++)
            {
                _leafHashes[idx] = Blake2SPCreateLeaf((ulong)idx);
            }
        }
예제 #7
0
        /// <summary>
        ///     Decode a miniLock ID into a byte array.
        /// </summary>
        /// <param name="encodedPublicKey">The miniLock ID.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="CorruptIdentityException"></exception>
        /// <returns>A 32 byte array.</returns>
        public static byte[] DecodeMiniLockPublicKey(string encodedPublicKey)
        {
            if (encodedPublicKey == null)
            {
                throw new ArgumentNullException("encodedPublicKey", "encodedPublicKey cannot be null");
            }

            var raw       = Base58CheckEncoding.DecodePlain(encodedPublicKey);
            var publicKey = ArrayHelper.SubArray(raw, 0, 32);
            var checksum  = ArrayHelper.SubArray(raw, 32);

            // validate the checksum
            if (!checksum.SequenceEqual(Blake2S.Hash(publicKey, (byte[])null, 1)))
            {
                throw new CorruptIdentityException("the given identity seems to be an invalid miniLock ID");
            }

            return(publicKey);
        }
예제 #8
0
        public void Test()
        {
            var vectors = new List <TestVector>
            {
                new TestVector
                {
                    Id        = 1,
                    InputHex  = "",
                    KeyHex    = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
                    ResultHex = "48a8997da407876b3d79c0d92325ad3b89cbb754d86ab71aee047ad345fd2c49"
                },
                new TestVector
                {
                    Id        = 2,
                    InputHex  = "00",
                    KeyHex    = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
                    ResultHex = "40d15fee7c328830166ac3f918650f807e7e01e177258cdc0a39b11f598066f1"
                },
                new TestVector
                {
                    Id        = 3,
                    InputHex  = "0001",
                    KeyHex    = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
                    ResultHex = "6bb71300644cd3991b26ccd4d274acd1adeab8b1d7914546c1198bbe9fc9d803"
                }
            };


            foreach (var vector in vectors)
            {
                var result = TestHelper.StringToByteArray(vector.ResultHex);
                var hash   = Blake2S.Hash(TestHelper.StringToByteArray(vector.InputHex),
                                          TestHelper.StringToByteArray(vector.KeyHex), result.Length);
                CollectionAssert.AreEqual(result, hash);
                Console.WriteLine("Test Vector " + vector.Id + ": passed");
            }
        }
예제 #9
0
        /// <summary>
        ///     Generate a MiniLock Keypair from an email and a password.
        /// </summary>
        /// <param name="email">A valid (format) email address.</param>
        /// <param name="password">A password with a minimal entropy of 100.</param>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="InvalidMailException"></exception>
        /// <exception cref="LowEntropyException"></exception>
        /// <returns>A libsodium compatible KeyPair.</returns>
        public static KeyPair GenerateMiniLockKeyPair(string email, string password)
        {
            const int minPasswordEntropy = 100;

            if (email == null)
            {
                throw new ArgumentNullException("email", "email cannot be null");
            }

            // perform a simple email check
            if (!StringHelper.IsValidEmail(email))
            {
                throw new InvalidMailException("the given email address seems to be invalid");
            }

            if (password == null)
            {
                throw new ArgumentNullException("password", "password cannot be null");
            }

            var passwordEntropy = Zxcvbn.Zxcvbn.MatchPassword(password).Entropy;

            // check the entropy
            if (passwordEntropy < 100)
            {
                throw new LowEntropyException(
                          string.Format(
                              "miniLock needs at least an entropy of {0}, the given password only has an entropy of {1}.",
                              minPasswordEntropy, passwordEntropy));
            }

            var passwordHash = Blake2S.Hash(Encoding.UTF8.GetBytes(password), (byte[])null, 32);
            var seed         = SCrypt.ComputeDerivedKey(passwordHash, Encoding.UTF8.GetBytes(email), 131072, 8, 1, 1, 32);
            var keyPair      = PublicKeyBox.GenerateKeyPair(seed);

            return(keyPair);
        }
예제 #10
0
            /// <summary>
            /// Creates the hasher.
            /// </summary>
            private HashAlgorithm CreateHasher()
            {
                var hasher = SrpHash.CreateHasher(H);

                if (hasher == null)
                {
                    HashAlgorithm blake2s() =>
                    Blake2S.Create().AsHashAlgorithm();

                    HashAlgorithm blake2b(int bits) =>
                    new Blake2BHasher(new Blake2BConfig {
                        OutputSizeInBits = bits
                    })
                    .AsHashAlgorithm();

                    switch (H.ToLowerInvariant())
                    {
                    case "blake2s-256":
                        return(blake2s());

                    case "blake2b-224":
                        return(blake2b(224));

                    case "blake2b-256":
                        return(blake2b(256));

                    case "blake2b-384":
                        return(blake2b(384));

                    case "blake2b-512":
                        return(blake2b(512));
                    }
                }

                return(hasher);
            }