/// <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); }
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]); }