コード例 #1
0
ファイル: MainForm.cs プロジェクト: ThatSlyGuy/SecretSplitter
        private void GenerateRandomFileKey()
        {
            // BONUS: you can specify however many characters you want ;)
            var match = Regex.Match(cboKeySizes.Text, @"(?<charCount>[0-9]+)\s*characters\s*\((?<bitCount>[0-9]+)\s*bits\s*\)");

            if (!match.Success)
            {
                ShowError("Specify a valid key size", "Invalid Key Size");
                return;
            }

            var charSize = Int32.Parse(match.Groups["charCount"].Value);
            var bitSize  = Int32.Parse(match.Groups["bitCount"].Value);

            // every char is 4 bits
            var charBitSize = charSize * 4;

            // If there is disagreement, pick the bigger one
            var maxBitSize = Math.Max(charBitSize, bitSize);

            txtMasterKey.Text = HexadecimalPasswordGenerator.GeneratePasswordOfBitSize(maxBitSize);
        }
コード例 #2
0
        private static void SplitFile()
        {
            // If your message is above 1K, you should use the hybrid approach of splitting the master secret
            // (which is the encryption key) and then use that to encrypt the file using OpenPGP and AES.

            // Here's an example of how to do this hybrid approach:

            // First, get a master secret of whatever size you want. 128 bits is plenty big and is a nice
            // balance of share sizes and security. However, to be fun, let's be super paranoid and go with
            // 256 bits (at the cost of bigger shares!)
            var masterPassword      = HexadecimalPasswordGenerator.GeneratePasswordOfBitSize(bitSize: 256);
            var masterPasswordBytes = SecretEncoder.ParseHexString(masterPassword);

            // As mentioned above, the threshold is the total number of shares that need to come together
            // to unlock the secret.
            const int threshold = 3;

            // Now we create a class to help us encrypt everything else:
            var splitSecret = SecretSplitter.SplitFile(masterPasswordBytes, threshold);

            // We can generate as many shares as we'd like knowing that 3 of them need to come together
            // to reconstruct the secret.
            const int totalShares = 5;
            var       shares      = splitSecret.GetShares(totalShares);

            // The textual representation is what you'd typically distribute:
            var sharesText = shares.Select(s => s.ToString()).ToList();

            // Remember that the shares are just mechanisms to distribute the master password. You still
            // need to distribute the encrypted file

            // Normally, you'd probably use the simpler method of
            // splitSecret.EncryptFile(inputPath, outputPath);

            // But this sample will use the more generic stream based version to keep everything in memory

            // Let's get a spot to store the encrypted output
            Stream encryptedStream;

            // First, let's make up a sample message of the numbers 1-1000
            // As mentioned before, normally you'd just use a simple file name with EncryptFile or an
            // existing stream:

            // The OpenPGP format stores the name of the file, so we provide that here. It can be whatever
            // you want
            const string fileNameInsideEncryptedContainer = "numbers.txt";

            using (var inputStream = new MemoryStream())
                using (var streamWriter = new StreamWriter(inputStream)) {
                    // Generate the numbers 1..1000 each on a single line
                    for (int i = 1; i <= 1000; i++)
                    {
                        streamWriter.WriteLine(i);
                    }

                    // we're done writing
                    streamWriter.Flush();

                    // Note that the size is bigger than 1250 bytes (the limit of splitting the message itself):
                    Debug.Assert(inputStream.Length > 1250);

                    // Now we can use the input. Reset its position to the start of the stream:
                    inputStream.Position = 0;

                    // Finally, encrypt the file. Save it with the filename metadata:
                    encryptedStream = splitSecret.Encrypt(inputStream, fileNameInsideEncryptedContainer);
                }

            // We can save the contents of outputStream wherever we'd like. It's encrypted.

            // Let's go ahead and decrypt it.

            // First, take the threshold number of shares to recover the master secret:
            var combinedSecret = SecretCombiner.Combine(sharesText.Take(threshold));

            // This metadata is present inside the encrypted file
            string   decryptedFileName;
            DateTime decryptedFileDateTime;

            using (var decryptedStream = combinedSecret.Decrypt(encryptedStream, out decryptedFileName, out decryptedFileDateTime))
                using (var decryptedStreamReader = new StreamReader(decryptedStream)) {
                    // For fun, verify the decrypted file is what we expect:

                    Debug.Assert(decryptedFileName == fileNameInsideEncryptedContainer);
                    for (int expectedNumber = 1; expectedNumber <= 1000; expectedNumber++)
                    {
                        var currentLineText   = decryptedStreamReader.ReadLine();
                        var currentLineNumber = Int32.Parse(currentLineText);
                        Debug.Assert(currentLineNumber == expectedNumber);
                    }

                    // Nothing left:
                    Debug.Assert(decryptedStreamReader.EndOfStream);
                }
        }