Пример #1
0
        /// <summary>
        ///     Validate a file with a MinisignSignature and a MinisignPublicKey object.
        /// </summary>
        /// <param name="message">The message to validate.</param>
        /// <param name="signature">A valid MinisignSignature object.</param>
        /// <param name="publicKey">A valid MinisignPublicKey object.</param>
        /// <returns><c>true</c> if valid; otherwise, <c>false</c>.</returns>
        /// <exception cref="OverflowException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static bool ValidateSignature(byte[] message, MinisignSignature signature, MinisignPublicKey publicKey)
        {
            if (message == null)
                throw new ArgumentException("missing signature input", "message");

            if (signature == null)
                throw new ArgumentException("missing signature input", "signature");

            if (publicKey == null)
                throw new ArgumentException("missing publicKey input", "publicKey");

            if (!ArrayHelpers.ConstantTimeEquals(signature.KeyId, publicKey.KeyId)) return false;
            // verify the signature
            if (PublicKeyAuth.VerifyDetached(signature.Signature, message, publicKey.PublicKey))
            {
                // verify the trusted comment
                return PublicKeyAuth.VerifyDetached(signature.GlobalSignature,
                    ArrayHelpers.ConcatArrays(signature.Signature, signature.TrustedComment), publicKey.PublicKey);
            }

            return false;
        }
Пример #2
0
        /// <summary>
        ///     Generate a new Minisign key pair.
        /// </summary>
        /// <param name="password">The password to protect the secret key.</param>
        /// <param name="writeOutputFiles">If false, no files will be written.</param>
        /// <param name="outputFolder">The folder to write the files (optional).</param>
        /// <param name="keyPairFileName">The name of the files to write (optional).</param>
        /// <returns>A MinisignKeyPair object.</returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="OverflowException"></exception>
        /// <exception cref="DirectoryNotFoundException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="IOException"></exception>
        /// <exception cref="UnauthorizedAccessException"></exception>
        /// <exception cref="PathTooLongException"></exception>
        /// <exception cref="SecurityException"></exception>
        /// <exception cref="NotSupportedException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static MinisignKeyPair GenerateKeyPair(string password, bool writeOutputFiles = false,
			string outputFolder = "", string keyPairFileName = "minisign")
        {
            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException("password", "password can not be null");
            }

            if (writeOutputFiles)
            {
                //validate the outputFolder
                if (string.IsNullOrEmpty(outputFolder) || !Directory.Exists(outputFolder))
                {
                    throw new DirectoryNotFoundException("outputFolder must exist");
                }

                if (outputFolder.IndexOfAny(Path.GetInvalidPathChars()) > -1)
                    throw new ArgumentException("The given path to the output folder contains invalid characters!");

                //validate the keyPairFileName
                if (string.IsNullOrEmpty(keyPairFileName))
                {
                    throw new ArgumentNullException("keyPairFileName", "keyPairFileName can not be empty");
                }
            }

            var minisignKeyPair = new MinisignKeyPair();
            var minisignPrivateKey = new MinisignPrivateKey();
            var keyPair = PublicKeyAuth.GenerateKeyPair();
            var keyId = SodiumCore.GetRandomBytes(KeyNumBytes);
            var kdfSalt = SodiumCore.GetRandomBytes(32);

            minisignPrivateKey.PublicKey = keyPair.PublicKey;
            minisignPrivateKey.KdfSalt = kdfSalt;
            minisignPrivateKey.SignatureAlgorithm = Encoding.UTF8.GetBytes(Sigalg);
            minisignPrivateKey.ChecksumAlgorithm = Encoding.UTF8.GetBytes(Chkalg);
            minisignPrivateKey.KdfAlgorithm = Encoding.UTF8.GetBytes(Kdfalg);
            minisignPrivateKey.KdfMemLimit = 1073741824; //currently unused
            minisignPrivateKey.KdfOpsLimit = 33554432; //currently unused

            var checksum =
                GenericHash.Hash(
                    ArrayHelpers.ConcatArrays(minisignPrivateKey.SignatureAlgorithm, keyId, keyPair.PrivateKey), null,
                    32);
            minisignPrivateKey.KeyId = keyId;
            minisignPrivateKey.SecretKey = keyPair.PrivateKey;
            minisignPrivateKey.Checksum = checksum;

            var dataToProtect = ArrayHelpers.ConcatArrays(keyId, keyPair.PrivateKey, checksum);
            var encryptionKey = PasswordHash.ScryptHashBinary(Encoding.UTF8.GetBytes(password),
                minisignPrivateKey.KdfSalt,
                PasswordHash.Strength.Sensitive,
                104);

            var encryptedKeyData = EncryptionHelpers.Xor(dataToProtect, encryptionKey);
            // set up the public key
            var minisignPublicKey = new MinisignPublicKey();
            minisignPublicKey.KeyId = keyId;
            minisignPublicKey.PublicKey = keyPair.PublicKey;
            minisignPublicKey.SignatureAlgorithm = Encoding.UTF8.GetBytes(Sigalg);
            keyPair.Dispose();
            if (writeOutputFiles)
            {
                var privateKeyOutputFileName = Path.Combine(outputFolder, keyPairFileName + PrivateKeyFileSuffix);
                var publicKeyOutputFileName = Path.Combine(outputFolder, keyPairFileName + PublicKeyFileSuffix);

                var binaryPublicKey = ArrayHelpers.ConcatArrays(
                    minisignPublicKey.SignatureAlgorithm,
                    minisignPublicKey.KeyId,
                    minisignPublicKey.PublicKey
                    );

                var publicFileContent = new[]
                {
                    CommentPrefix + "minisign public key " +
                    Utilities.BinaryToHex(minisignPublicKey.KeyId, Utilities.HexFormat.None, Utilities.HexCase.Upper),
                    Convert.ToBase64String(binaryPublicKey)
                };

                var binaryPrivateKey = ArrayHelpers.ConcatArrays(
                    minisignPrivateKey.SignatureAlgorithm,
                    minisignPrivateKey.KdfAlgorithm,
                    minisignPrivateKey.ChecksumAlgorithm,
                    minisignPrivateKey.KdfSalt,
                    BitConverter.GetBytes(minisignPrivateKey.KdfOpsLimit),
                    BitConverter.GetBytes(minisignPrivateKey.KdfMemLimit),
                    encryptedKeyData
                    );

                var privateFileContent = new[]
                {
                    CommentPrefix + PrivateKeyDefaultComment,
                    Convert.ToBase64String(binaryPrivateKey)
                };
                // files will be overwritten!
                File.WriteAllLines(publicKeyOutputFileName, publicFileContent);
                File.WriteAllLines(privateKeyOutputFileName, privateFileContent);

                minisignKeyPair.MinisignPublicKeyFilePath = publicKeyOutputFileName;
                minisignKeyPair.MinisignPrivateKeyFilePath = privateKeyOutputFileName;
            }

            minisignKeyPair.MinisignPublicKey = minisignPublicKey;
            minisignKeyPair.MinisignPrivateKey = minisignPrivateKey;
            return minisignKeyPair;
        }
Пример #3
0
        /// <summary>
        ///     Validate a file with a MinisignSignature and a MinisignPublicKey object.
        /// </summary>
        /// <param name="filePath">The full path to the file.</param>
        /// <param name="signature">A valid MinisignSignature object.</param>
        /// <param name="publicKey">A valid MinisignPublicKey object.</param>
        /// <returns><c>true</c> if valid; otherwise, <c>false</c>.</returns>
        /// <exception cref="FileNotFoundException"></exception>
        /// <exception cref="OverflowException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static bool ValidateSignature(string filePath, MinisignSignature signature, MinisignPublicKey publicKey)
        {
            if (filePath != null && !File.Exists(filePath))
            {
                throw new FileNotFoundException("could not find filePath");
            }

            if (signature == null)
                throw new ArgumentException("missing signature input", "signature");

            if (publicKey == null)
                throw new ArgumentException("missing publicKey input", "publicKey");

            if (!ArrayHelpers.ConstantTimeEquals(signature.KeyId, publicKey.KeyId)) return false;
            // load the file into memory
            var file = LoadMessageFile(filePath);
            // verify the signature
            if (PublicKeyAuth.VerifyDetached(signature.Signature, file, publicKey.PublicKey))
            {
                // verify the trusted comment
                return PublicKeyAuth.VerifyDetached(signature.GlobalSignature,
                    ArrayHelpers.ConcatArrays(signature.Signature, signature.TrustedComment), publicKey.PublicKey);
            }

            return false;
        }
Пример #4
0
        /// <summary>
        ///     Load a public key into a MinisignPublicKey object.
        /// </summary>
        /// <param name="publicKey">A valid public key.</param>
        /// <returns>A MinisignPublicKey object.</returns>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="OverflowException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public static MinisignPublicKey LoadPublicKey(byte[] publicKey)
        {
            if (publicKey == null)
                throw new ArgumentException("missing publicKey input", "publicKey");

            var minisignPublicKey = new MinisignPublicKey
            {
                SignatureAlgorithm = ArrayHelpers.SubArray(publicKey, 0, 2),
                KeyId = ArrayHelpers.SubArray(publicKey, 2, 8),
                PublicKey = ArrayHelpers.SubArray(publicKey, 10)
            };

            return minisignPublicKey;
        }