Beispiel #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", nameof(message));
            }

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

            if (publicKey == null)
            {
                throw new ArgumentException("missing publicKey input", nameof(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);
        }
Beispiel #2
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", nameof(signature));
            }

            if (publicKey == null)
            {
                throw new ArgumentException("missing publicKey input", nameof(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);
        }
Beispiel #3
0
        /// <summary>
        ///     Load a public key into a MinisignPublicKey object.
        /// </summary>
        /// <param name="privateKey">A valid private key.</param>
        /// <param name="password">The password to decrypt the private key.</param>
        /// <returns>A MinisignPrivateKey object.</returns>
        /// <exception cref="OverflowException"></exception>
        /// <exception cref="CorruptPrivateKeyException"></exception>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        /// <exception cref="ArgumentException"></exception>
        /// <exception cref="ArgumentNullException"></exception>
        public static MinisignPrivateKey LoadPrivateKey(byte[] privateKey, byte[] password)
        {
            if (privateKey == null)
            {
                throw new ArgumentException("missing privateKey input", nameof(privateKey));
            }

            if (password == null)
            {
                throw new ArgumentException("missing password input", nameof(password));
            }

            var minisignPrivateKey = new MinisignPrivateKey
            {
                SignatureAlgorithm = ArrayHelpers.SubArray(privateKey, 0, 2),
                KdfAlgorithm       = ArrayHelpers.SubArray(privateKey, 2, 2),
                ChecksumAlgorithm  = ArrayHelpers.SubArray(privateKey, 4, 2),
                KdfSalt            = ArrayHelpers.SubArray(privateKey, 6, 32),
                KdfOpsLimit        = BitConverter.ToInt64(ArrayHelpers.SubArray(privateKey, 38, 8), 0),         //currently unused
                KdfMemLimit        = BitConverter.ToInt64(ArrayHelpers.SubArray(privateKey, 46, 8), 0)          //currently unused
            };

            if (!minisignPrivateKey.SignatureAlgorithm.SequenceEqual(Encoding.UTF8.GetBytes(Sigalg)))
            {
                throw new CorruptPrivateKeyException("bad SignatureAlgorithm");
            }

            if (!minisignPrivateKey.ChecksumAlgorithm.SequenceEqual(Encoding.UTF8.GetBytes(Chkalg)))
            {
                throw new CorruptPrivateKeyException("bad ChecksumAlgorithm");
            }

            if (!minisignPrivateKey.KdfAlgorithm.SequenceEqual(Encoding.UTF8.GetBytes(Kdfalg)))
            {
                throw new CorruptPrivateKeyException("bad KdfAlgorithm");
            }

            if (minisignPrivateKey.KdfSalt.Length != KeySaltBytes)
            {
                throw new CorruptPrivateKeyException("bad KdfSalt length");
            }

            var encryptedKeyData = ArrayHelpers.SubArray(privateKey, 54, 104);

            var decryptionKey = PasswordHash.ScryptHashBinary(password, minisignPrivateKey.KdfSalt,
                                                              PasswordHash.Strength.Sensitive,
                                                              104);

            var decryptedKeyData = EncryptionHelpers.Xor(encryptedKeyData, decryptionKey);

            minisignPrivateKey.KeyId     = ArrayHelpers.SubArray(decryptedKeyData, 0, 8);
            minisignPrivateKey.SecretKey = ArrayHelpers.SubArray(decryptedKeyData, 8, 64);
            minisignPrivateKey.Checksum  = ArrayHelpers.SubArray(decryptedKeyData, 72, 32);

            if (minisignPrivateKey.KeyId.Length != KeyNumBytes)
            {
                throw new CorruptPrivateKeyException("bad KeyId length");
            }

            var calculatedChecksum =
                GenericHash.Hash(
                    ArrayHelpers.ConcatArrays(minisignPrivateKey.SignatureAlgorithm, minisignPrivateKey.KeyId,
                                              minisignPrivateKey.SecretKey), null, 32);

            if (!ArrayHelpers.ConstantTimeEquals(minisignPrivateKey.Checksum, calculatedChecksum))
            {
                throw new CorruptPrivateKeyException("bad private key checksum");
            }
            // extract the public key from the private key
            minisignPrivateKey.PublicKey =
                PublicKeyAuth.ExtractEd25519PublicKeyFromEd25519SecretKey(minisignPrivateKey.SecretKey);

            return(minisignPrivateKey);
        }