Example #1
0
        internal ImmutableArray <byte> GetHash(AssemblyHashAlgorithm algorithmId)
        {
            using (HashAlgorithm? algorithm = TryGetAlgorithm(algorithmId))
            {
                // ERR_CryptoHashFailed has already been reported:
                if (algorithm == null)
                {
                    return(ImmutableArray.Create <byte>());
                }

                switch (algorithmId)
                {
                case AssemblyHashAlgorithm.None:
                case AssemblyHashAlgorithm.Sha1:
                    return(GetHash(ref _lazySHA1Hash, algorithm));

                case AssemblyHashAlgorithm.Sha256:
                    return(GetHash(ref _lazySHA256Hash, algorithm));

                case AssemblyHashAlgorithm.Sha384:
                    return(GetHash(ref _lazySHA384Hash, algorithm));

                case AssemblyHashAlgorithm.Sha512:
                    return(GetHash(ref _lazySHA512Hash, algorithm));

                case AssemblyHashAlgorithm.MD5:
                    return(GetHash(ref _lazyMD5Hash, algorithm));

                default:
                    throw ExceptionUtilities.UnexpectedValue(algorithmId);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Constructor for the Checksum class used for computing file checksum.
        /// </summary>
        /// <param name="algorithm">Algorithm to be used for hashing.</param>
        /// <remarks>
        /// Supported hash algorithms: { MD5, SHA1, SHA256 }.
        /// If <see langword="Algorithm.None" />, do not compute any file hash.
        /// Default hash algorithm is MD5, if input algorithm is unsupported or null.
        /// </remarks>
        public Checksum(Algorithm algorithm)
        {
            switch (algorithm)
            {
            case Algorithm.None:
                _hashAlgorithm = null;
                AlgorithmName  = new HashAlgorithmName("None");
                break;

            case Algorithm.SHA1:
                _hashAlgorithm = SHA1.Create();
                AlgorithmName  = HashAlgorithmName.SHA1;
                break;

            case Algorithm.SHA256:
                _hashAlgorithm = SHA256.Create();
                AlgorithmName  = HashAlgorithmName.SHA256;
                break;

            case Algorithm.MD5:
            default:
                _hashAlgorithm = MD5.Create();
                AlgorithmName  = HashAlgorithmName.MD5;
                break;
            }
            ;
        }
Example #3
0
        public override byte[] GenerateMask(byte[] rgbSeed, int cbReturn)
        {
            using (HashAlgorithm? hasher = CryptoConfig.CreateFromName(_hashNameValue) as HashAlgorithm)
            {
                if (hasher is null)
                {
                    throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, _hashNameValue));
                }

                byte[] rgbCounter = new byte[4];
                byte[] rgbT       = new byte[cbReturn];

                uint counter = 0;
                for (int ib = 0; ib < rgbT.Length;)
                {
                    //  Increment counter -- up to 2^32 * sizeof(Hash)
                    BinaryPrimitives.WriteUInt32BigEndian(rgbCounter, counter++);
                    hasher.TransformBlock(rgbSeed, 0, rgbSeed.Length, rgbSeed, 0);
                    hasher.TransformFinalBlock(rgbCounter, 0, 4);
                    Debug.Assert(hasher.Hash != null);
                    byte[] hash = hasher.Hash;
                    hasher.Initialize();
                    Buffer.BlockCopy(hash, 0, rgbT, ib, Math.Min(rgbT.Length - ib, hash.Length));

                    ib += hasher.Hash.Length;
                }

                return(rgbT);
            }
        }
Example #4
0
 public void Dispose()
 {
     if (_hashAlgorithm != null)
     {
         _hashAlgorithm.Dispose();
         _hashAlgorithm = null;
     }
 }
Example #5
0
 public void Dispose()
 {
     if (hashAlgorithm != null)
     {
         hashAlgorithm.Dispose();
         hashAlgorithm = null;
     }
 }
        public void HashAndVerify_Success()
        {
            string?       content   = File.ReadAllText("CryptoTest.txt");
            HashAlgorithm?algorithm = HashAlgorithm.Create("SHA256");
            string?       hash      = Cryptography.GetHash(algorithm, content);

            Assert.NotNull(hash);
            Assert.NotEmpty(hash);

            Assert.True(Cryptography.VerifyHash(algorithm, content, hash));
        }
        public void HashAndVerify_Fail()
        {
            string?       content   = File.ReadAllText("CryptoTest.txt");
            HashAlgorithm?algorithm = HashAlgorithm.Create("SHA256");
            string?       hash      = Cryptography.GetHash(algorithm, content);

            string?reverseContent = content.ToArray().Reverse().ToString();
            string?hash2          = Cryptography.GetHash(algorithm, reverseContent);

            Assert.False(Cryptography.VerifyHash(algorithm, content, hash2));
            Assert.False(Cryptography.VerifyHash(algorithm, reverseContent, hash));
        }
Example #8
0
        public bool Parse(string challenge)
        {
            parser = new AuthDigestHeaderParser(challenge);
            if (!parser.Parse())
            {
                return(false);
            }

            // build the hash object (only MD5 is defined in RFC2617)
            if ((parser.Algorithm == null) || (parser.Algorithm.StartsWith("MD5", StringComparison.OrdinalIgnoreCase)))
            {
                hash = MD5.Create();
            }

            return(true);
        }
Example #9
0
    /// <summary>
    /// 获取Hash后的字节数组
    /// </summary>
    /// <param name="type">哈希类型</param>
    /// <param name="key">key</param>
    /// <param name="bytes">原字节数组</param>
    /// <returns></returns>
    public static byte[]? GetHashedBytes(this IHashGenerater _, HashType type, byte[] bytes, byte[]?key)
    {
        if (null == bytes)
        {
            return(bytes);
        }

        HashAlgorithm?algorithm = null;

        try
        {
            if (key == null)
            {
                algorithm = type switch
                {
                    HashType.MD5 => MD5.Create(),
                    HashType.SHA1 => SHA1.Create(),
                    HashType.SHA256 => SHA256.Create(),
                    HashType.SHA384 => SHA384.Create(),
                    HashType.SHA512 => SHA512.Create(),
                    _ => MD5.Create(),
                };
            }
            else
            {
                algorithm = type switch
                {
                    HashType.MD5 => new HMACMD5(key),
                    HashType.SHA1 => new HMACSHA1(key),
                    HashType.SHA256 => new HMACSHA256(key),
                    HashType.SHA384 => new HMACSHA384(key),
                    HashType.SHA512 => new HMACSHA512(key),
                    _ => new HMACMD5(key),
                };
            }
            return(algorithm.ComputeHash(bytes));
        }
        finally
        {
            algorithm?.Dispose();
        }
    }
Example #10
0
        protected override void InnerDispose()
        {
            try
            {
                if (_hasher != null)
                {
                    if (_result == null && _onResult != null)
                    {
                        FinishHashing();
                    }

                    _hasher.Dispose();
                }
            }
            finally
            {
                _hasher = null;
                base.InnerDispose();
            }
        }
Example #11
0
        /// <summary>
        /// Get the hash for an input.
        /// </summary>
        /// <param name="hashAlgorithm">The hash algorithm to use.</param>
        /// <param name="input">The content to hash.</param>
        /// <returns>A string hash.</returns>
        public static string GetHash(HashAlgorithm?hashAlgorithm, string?input)
        {
            ArgumentNullException.ThrowIfNull(hashAlgorithm);
            if (string.IsNullOrWhiteSpace(input))
            {
                throw new ArgumentNullException(nameof(input));
            }

            // Convert the input string to a byte array and compute the hash.
            byte[] data = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(input));

            // Loop through each byte of the hashed data and format each one as a hexadecimal string.
            var sBuilder = new StringBuilder();

            for (int d = 0; d < data.Length; d++)
            {
                sBuilder.Append(data[d].ToString("x2"));
            }

            return(sBuilder.ToString());
        }
Example #12
0
        private static string GetCrlFileName(SafeX509Handle cert, string crlUrl)
        {
            // X509_issuer_name_hash returns "unsigned long", which is marshalled as ulong.
            // But it only sets 32 bits worth of data, so force it down to uint just... in case.
            ulong persistentHashLong = Interop.Crypto.X509IssuerNameHash(cert);

            if (persistentHashLong == 0)
            {
                Interop.Crypto.ErrClearError();
            }

            uint persistentHash = unchecked ((uint)persistentHashLong);

            if (ts_urlHash == null)
            {
                ts_urlHash = SHA256.Create();
            }

            Span <byte> hash = stackalloc byte[256 >> 3];

            // Endianness isn't important, it just needs to be consistent.
            // (Even if the same storage was used for two different endianness systems it'd stabilize at two files).
            ReadOnlySpan <byte> utf16Url = MemoryMarshal.AsBytes(crlUrl.AsSpan());

            if (!ts_urlHash.TryComputeHash(utf16Url, hash, out int written) || written != hash.Length)
            {
                Debug.Fail("TryComputeHash failed or produced an incorrect length output");
                throw new CryptographicException();
            }

            uint urlHash = MemoryMarshal.Read <uint>(hash);

            // OpenSSL's hashed filename algorithm is the 8-character hex version of the 32-bit value
            // of X509_issuer_name_hash (or X509_subject_name_hash, depending on the context).
            //
            // We mix in an 8-character hex version of the "left"-most bytes of a hash of the URL to
            // disambiguate when one Issuing Authority separates their revocation across independent CRLs.
            return($"{persistentHash:x8}.{urlHash:x8}.crl");
        }
        public async Task HashAndVerify_TwoFilesAsync()
        {
            string?tempFilename = Path.GetTempFileName();

            try
            {
                HashAlgorithm?algorithm = HashAlgorithm.Create("SHA256");

                FileStream?tempFile = File.Create(tempFilename);

                FileInfo?fileInfo1 = new("CryptoTest.txt");
                FileInfo?fileInfo2 = new(tempFilename);

                string?content1 = File.ReadAllText(fileInfo1.FullName);

                // Make the second file identical except for an additional newline character.
                byte[]? buffer = Encoding.UTF8.GetBytes($"{content1}{Environment.NewLine}");
                await tempFile.WriteAsync(buffer.AsMemory(0, buffer.Length));

                await tempFile.FlushAsync();

                tempFile.Close();

                string?hash1 = Cryptography.GetHashForFile(algorithm, fileInfo1);
                string?hash2 = Cryptography.GetHashForFile(algorithm, fileInfo2);

                Assert.NotEqual(hash1, hash2);

                Assert.True(Cryptography.VerifyHashForFile(algorithm, fileInfo1, hash1));
                Assert.True(Cryptography.VerifyHashForFile(algorithm, fileInfo2, hash2));

                Assert.False(Cryptography.VerifyHashForFile(algorithm, fileInfo1, hash2));
                Assert.False(Cryptography.VerifyHashForFile(algorithm, fileInfo2, hash1));
            }
            finally
            {
                File.Delete(tempFilename);
            }
        }
Example #14
0
 /// <summary>
 /// Creates an instance of name based RFC4122 UUID generator.
 /// Either Version-3 (MD5 hashing) or Version-5 (SHA-1 hashing) variant is instantiated based on  <paramref name="hashType"/>.
 /// </summary>
 /// <param name="hashType">Hashing algorithm type be used (MD5 or SHA-1)</param>
 public NameBasedGenerator(HashType hashType)
 {
     _hashAlgorithm = hashType == HashType.Md5 ? (HashAlgorithm)MD5.Create() : SHA1.Create();
     _version       = hashType == HashType.Md5 ? UUIDVersion.NameBasedWithMd5 : UUIDVersion.NamedBasedWithSha1;
 }
Example #15
0
 public CreateHashBucket(Bucket inner, HashAlgorithm hasher)
     : base(inner)
 {
     _hasher = hasher ?? throw new ArgumentNullException(nameof(hasher));
 }
Example #16
0
        async Task AuthenticateSASL(List <string> mechanisms, string username, bool async, CancellationToken cancellationToken = default)
        {
            // At the time of writing PostgreSQL only supports SCRAM-SHA-256 and SCRAM-SHA-256-PLUS
            var supportsSha256     = mechanisms.Contains("SCRAM-SHA-256");
            var supportsSha256Plus = mechanisms.Contains("SCRAM-SHA-256-PLUS");

            if (!supportsSha256 && !supportsSha256Plus)
            {
                throw new NpgsqlException("No supported SASL mechanism found (only SCRAM-SHA-256 and SCRAM-SHA-256-PLUS are supported for now). " +
                                          "Mechanisms received from server: " + string.Join(", ", mechanisms));
            }

            var mechanism      = string.Empty;
            var cbindFlag      = string.Empty;
            var cbind          = string.Empty;
            var successfulBind = false;

            if (supportsSha256Plus)
            {
                var sslStream = (SslStream)_stream;
                if (sslStream.RemoteCertificate is null)
                {
                    Log.Warn("Remote certificate null, falling back to SCRAM-SHA-256");
                }
                else
                {
                    using var remoteCertificate = new X509Certificate2(sslStream.RemoteCertificate);
                    // Checking for hashing algorithms
                    HashAlgorithm?hashAlgorithm = null;
                    var           algorithmName = remoteCertificate.SignatureAlgorithm.FriendlyName;
                    if (algorithmName is null)
                    {
                        Log.Warn("Signature algorithm was null, falling back to SCRAM-SHA-256");
                    }
                    else if (algorithmName.StartsWith("sha1", StringComparison.OrdinalIgnoreCase) ||
                             algorithmName.StartsWith("md5", StringComparison.OrdinalIgnoreCase) ||
                             algorithmName.StartsWith("sha256", StringComparison.OrdinalIgnoreCase))
                    {
                        hashAlgorithm = SHA256.Create();
                    }
                    else if (algorithmName.StartsWith("sha384", StringComparison.OrdinalIgnoreCase))
                    {
                        hashAlgorithm = SHA384.Create();
                    }
                    else if (algorithmName.StartsWith("sha512", StringComparison.OrdinalIgnoreCase))
                    {
                        hashAlgorithm = SHA512.Create();
                    }
                    else
                    {
                        Log.Warn($"Support for signature algorithm {algorithmName} is not yet implemented, falling back to SCRAM-SHA-256");
                    }

                    if (hashAlgorithm != null)
                    {
                        using var _ = hashAlgorithm;

                        // RFC 5929
                        mechanism = "SCRAM-SHA-256-PLUS";
                        // PostgreSQL only supports tls-server-end-point binding
                        cbindFlag = "p=tls-server-end-point";
                        // SCRAM-SHA-256-PLUS depends on using ssl stream, so it's fine
                        var cbindFlagBytes = Encoding.UTF8.GetBytes($"{cbindFlag},,");

                        var certificateHash = hashAlgorithm.ComputeHash(remoteCertificate.GetRawCertData());
                        var cbindBytes      = cbindFlagBytes.Concat(certificateHash).ToArray();
                        cbind          = Convert.ToBase64String(cbindBytes);
                        successfulBind = true;
                        IsScramPlus    = true;
                    }
                }
            }

            if (!successfulBind && supportsSha256)
            {
                mechanism = "SCRAM-SHA-256";
                // We can get here if PostgreSQL supports only SCRAM-SHA-256 or there was an error while binding to SCRAM-SHA-256-PLUS
                // So, we set 'n' (client does not support binding) if there was an error while binding
                // or 'y' (client supports but server doesn't) in other case
                cbindFlag      = supportsSha256Plus ? "n" : "y";
                cbind          = supportsSha256Plus ? "biws" : "eSws";
                successfulBind = true;
                IsScram        = true;
            }

            if (!successfulBind)
            {
                // We can get here if PostgreSQL supports only SCRAM-SHA-256-PLUS but there was an error while binding to it
                throw new NpgsqlException("Unable to bind to SCRAM-SHA-256-PLUS, check logs for more information");
            }

            var passwd = GetPassword(username) ??
                         throw new NpgsqlException($"No password has been provided but the backend requires one (in SASL/{mechanism})");

            // Assumption: the write buffer is big enough to contain all our outgoing messages
            var clientNonce = GetNonce();

            await WriteSASLInitialResponse(mechanism, PGUtil.UTF8Encoding.GetBytes($"{cbindFlag},,n=*,r={clientNonce}"), async, cancellationToken);
            await Flush(async, cancellationToken);

            var saslContinueMsg = Expect <AuthenticationSASLContinueMessage>(await ReadMessage(async), this);

            if (saslContinueMsg.AuthRequestType != AuthenticationRequestType.AuthenticationSASLContinue)
            {
                throw new NpgsqlException("[SASL] AuthenticationSASLContinue message expected");
            }
            var firstServerMsg = AuthenticationSCRAMServerFirstMessage.Load(saslContinueMsg.Payload);

            if (!firstServerMsg.Nonce.StartsWith(clientNonce))
            {
                throw new NpgsqlException("[SCRAM] Malformed SCRAMServerFirst message: server nonce doesn't start with client nonce");
            }

            var saltBytes      = Convert.FromBase64String(firstServerMsg.Salt);
            var saltedPassword = Hi(passwd.Normalize(NormalizationForm.FormKC), saltBytes, firstServerMsg.Iteration);

            var clientKey = HMAC(saltedPassword, "Client Key");

            byte[] storedKey;
            using (var sha256 = SHA256.Create())
                storedKey = sha256.ComputeHash(clientKey);

            var clientFirstMessageBare         = $"n=*,r={clientNonce}";
            var serverFirstMessage             = $"r={firstServerMsg.Nonce},s={firstServerMsg.Salt},i={firstServerMsg.Iteration}";
            var clientFinalMessageWithoutProof = $"c={cbind},r={firstServerMsg.Nonce}";

            var authMessage = $"{clientFirstMessageBare},{serverFirstMessage},{clientFinalMessageWithoutProof}";

            var clientSignature  = HMAC(storedKey, authMessage);
            var clientProofBytes = Xor(clientKey, clientSignature);
            var clientProof      = Convert.ToBase64String(clientProofBytes);

            var serverKey       = HMAC(saltedPassword, "Server Key");
            var serverSignature = HMAC(serverKey, authMessage);

            var messageStr = $"{clientFinalMessageWithoutProof},p={clientProof}";

            await WriteSASLResponse(Encoding.UTF8.GetBytes(messageStr), async, cancellationToken);
            await Flush(async, cancellationToken);

            var saslFinalServerMsg = Expect <AuthenticationSASLFinalMessage>(await ReadMessage(async), this);

            if (saslFinalServerMsg.AuthRequestType != AuthenticationRequestType.AuthenticationSASLFinal)
            {
                throw new NpgsqlException("[SASL] AuthenticationSASLFinal message expected");
            }

            var scramFinalServerMsg = AuthenticationSCRAMServerFinalMessage.Load(saslFinalServerMsg.Payload);

            if (scramFinalServerMsg.ServerSignature != Convert.ToBase64String(serverSignature))
            {
                throw new NpgsqlException("[SCRAM] Unable to verify server signature");
            }

            var okMsg = Expect <AuthenticationRequestMessage>(await ReadMessage(async), this);

            if (okMsg.AuthRequestType != AuthenticationRequestType.AuthenticationOk)
            {
                throw new NpgsqlException("[SASL] Expected AuthenticationOK message");
            }
Example #17
0
 /// <summary>
 /// Verify the hash of a file.
 /// </summary>
 /// <param name="hashAlgorithm">The hash algorithm to use.</param>
 /// <param name="fileInfo">The file to hash.</param>
 /// <param name="hash">The expected hash.</param>
 /// <returns>True if the hashes match, otherwise false.</returns>
 public static bool VerifyHashForFile(HashAlgorithm?hashAlgorithm, FileInfo fileInfo, string hash) =>
 VerifyHash(hashAlgorithm, File.ReadAllText(fileInfo.FullName), hash);
Example #18
0
 public SM2DeriveBytes(ReadOnlySpan <byte> key, HashAlgorithm?hash = null)
 {
     _key    = new byte[key.Length + 4];
     _hasher = hash ?? new SM3();
     key.CopyTo(_key);
 }
        /// <summary>
        /// Computes the hash of the specified buffer and checks for a match to an expected hash.
        /// </summary>
        /// <param name="cryptoProvider">The crypto provider.</param>
        /// <param name="data">The data to hash.</param>
        /// <param name="expectedHash">The expected hash.</param>
        /// <param name="hashAlgorithm">The hash algorithm.</param>
        /// <returns>
        ///   <c>true</c> if the hashes came out equal; <c>false</c> otherwise.
        /// </returns>
        internal static bool IsHashMatchWithTolerantHashAlgorithm(this CryptoSettings cryptoProvider, byte[] data, byte[] expectedHash, HashAlgorithm? hashAlgorithm)
        {
            Requires.NotNull(cryptoProvider, "cryptoProvider");
            Requires.NotNull(data, "data");
            Requires.NotNull(expectedHash, "expectedHash");

            if (!hashAlgorithm.HasValue)
            {
                hashAlgorithm = Utilities.GuessHashAlgorithmFromLength(expectedHash.Length);
            }

            var hasher = WinRTCrypto.HashAlgorithmProvider.OpenAlgorithm(hashAlgorithm.Value);
            byte[] actualHash = hasher.HashData(data);
            return Utilities.AreEquivalent(expectedHash, actualHash);
        }
Example #20
0
 /// <summary>
 /// Verify the hash for a certain input.
 /// </summary>
 /// <param name="hashAlgorithm">The hash algorithm to use.</param>
 /// <param name="input">The content to hash.</param>
 /// <param name="hash">The expected hash.</param>
 /// <returns>True if the hashes match, otherwise false.</returns>
 public static bool VerifyHash(HashAlgorithm?hashAlgorithm, string?input, string?hash) =>
 StringComparer.OrdinalIgnoreCase.Compare(GetHash(hashAlgorithm, input), hash) == 0;
Example #21
0
 public HashingStreamEx(Stream sBaseStream, bool bWriting, HashAlgorithm?hashAlgorithm)
        /// <summary>
        /// Return an output stream which will encrypt the data as it is written to it.
        /// </summary>
        protected override IPacketWriter Open()
        {
            var writer = base.Open();

            if (cOut != null)
            {
                throw new InvalidOperationException("generator already in open state");
            }
            // TODO: Do we want compatibility with old PGP? (IDEA + no password iirc)
            if (methods.Count == 0)
            {
                throw new InvalidOperationException("No encryption methods specified");
            }

            var c = PgpUtilities.GetSymmetricAlgorithm(defAlgorithm);

            if (methods.Count == 1 && methods[0] is PbeMethod)
            {
                PbeMethod m = (PbeMethod)methods[0];
                c.Key = m.GetKey();
                writer.WritePacket(m.GetSessionInfoPacket());
            }
            else
            {
                c.GenerateKey();
                byte[] sessionInfo = CreateSessionInfo(defAlgorithm, c.Key);

                foreach (EncMethod m in methods)
                {
                    writer.WritePacket(m.GetSessionInfoPacket(sessionInfo));
                }
            }

            try
            {
                if (withIntegrityPacket)
                {
                    pOut = writer.GetPacketStream(new SymmetricEncIntegrityPacket());
                }
                else
                {
                    pOut = writer.GetPacketStream(new SymmetricEncDataPacket());
                }

                int    blockSize = (c.BlockSize + 7) / 8;
                byte[] inLineIv  = new byte[blockSize * 2]; // Aligned to block size
                RandomNumberGenerator.Fill(inLineIv.AsSpan(0, blockSize));
                inLineIv[blockSize]     = inLineIv[blockSize - 2];
                inLineIv[blockSize + 1] = inLineIv[blockSize - 1];

                ICryptoTransform encryptor;
                c.IV = new byte[blockSize];
                if (withIntegrityPacket)
                {
                    encryptor = c.CreateEncryptor();
                }
                else
                {
                    encryptor = c.CreateEncryptor();
                    var encryptedInlineIv = encryptor.TransformFinalBlock(inLineIv, 0, inLineIv.Length);
                    pOut.Write(encryptedInlineIv.AsSpan(0, blockSize + 2));
                    c.IV      = encryptedInlineIv.AsSpan(2, blockSize).ToArray();
                    encryptor = c.CreateEncryptor();
                }

                Stream myOut = cOut = new CryptoStream(pOut, new ZeroPaddedCryptoTransform(encryptor), CryptoStreamMode.Write);

                if (withIntegrityPacket)
                {
                    digest = SHA1.Create();
                    myOut  = digestOut = new CryptoStream(new FilterStream(myOut), digest, CryptoStreamMode.Write);
                    myOut.Write(inLineIv, 0, blockSize + 2);
                }

                return(writer.CreateNestedWriter(new WrappedGeneratorStream(myOut, _ => Close())));
            }
            catch (Exception e)
            {
                throw new PgpException("Exception creating cipher", e);
            }
        }
Example #23
0
        public unsafe X509Certificate2 GenerateCertificate(X509Certificate2 issuingCertificate, PrivateKey privateKey, X500DistinguishedName dn, string[] dnsNames, IPAddress[] ipAddresses = null, HashAlgorithm?signatureAlgorithm = null, DateTime?notBefore = null, DateTime?notAfter = null)
        {
            if (!issuingCertificate.HasPrivateKey)
            {
                throw new ArgumentException("Issuing certificate must have a private key.", nameof(issuingCertificate));
            }
            IntPtr basicEncodedDataPtr = IntPtr.Zero, certExtensionPtr = IntPtr.Zero;
            var    serialNumber = new byte[16];
            var    rng = RandomNumberGenerator.Create();

            rng.GetNonZeroBytes(serialNumber);
            serialNumber[15] &= 0x7F;
            fixed(byte *dnPtr = dn.RawData, issuerDnPtr = issuingCertificate.SubjectName.RawData, serialNumberPtr = serialNumber)
            {
                try
                {
                    var blob = new NATIVE_CRYPTOAPI_BLOB
                    {
                        cbData = (uint)dn.RawData.Length,
                        pbData = dnPtr
                    };
                    var signingSignatureAlgorithmIdentifier = new CRYPT_ALGORITHM_IDENTIFIER
                    {
                        pszObjId = issuingCertificate.SignatureAlgorithm.Value
                    };
                    using (var signingKey = ExtractKey(issuingCertificate))
                    {
                        var signingAlgorithmIdentifier = new CRYPT_ALGORITHM_IDENTIFIER
                        {
                            pszObjId = signatureAlgorithm != null?HashAlgorithmToSignatureAlgorithm(signingKey, signatureAlgorithm.Value) : issuingCertificate.SignatureAlgorithm.Value
                        };
                        using (PublicKeyInfo publicKey = privateKey.ToPublicKey(), signingPublicKey = signingKey.ToPublicKey())
                        {
                            using (var extensions = new MarshalX509ExtensionCollection())
                            {
                                using (extensions.Freeze())
                                {
                                    var usage = X509KeyUsageFlags.DigitalSignature;
                                    if (privateKey.AlgorithmGroup == AlgorithmGroup.RSA)
                                    {
                                        //Key encipherment is not valid for DSA/ECDSA
                                        usage |= X509KeyUsageFlags.KeyEncipherment;
                                    }
                                    extensions.Add(new X509BasicConstraintsExtension(false, false, 0, true));
                                    extensions.Add(new X509KeyUsageExtension(usage, true));
                                    extensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection {
                                        new Oid(OIDs.EKU_SERVER)
                                    }, false));
                                    extensions.Add(new X509SubjectAlternativeNameExtension(DnsAltNamesFromArray(dnsNames, ipAddresses ?? new IPAddress[0]), false));
                                    using (var sha1 = new SHA1CryptoServiceProvider())
                                    {
                                        var issuingKeyId = sha1.ComputeHash(signingPublicKey.Key);
                                        extensions.Add(new X509SubjectKeyIdentifierExtension(sha1.ComputeHash(publicKey.Key), false));
                                        extensions.Add(new X509AuthorityKeyIdentifierExtension(issuingKeyId, null));
                                    }
                                }
                                var certInfo = new CERT_INFO();
                                certInfo.Subject      = blob;
                                certInfo.SerialNumber = new NATIVE_CRYPTOAPI_BLOB {
                                    cbData = (uint)serialNumber.Length, pbData = serialNumberPtr
                                };
                                certInfo.SubjectPublicKeyInfo = publicKey.PublicKey;
                                certInfo.dwVersion            = CertificateVersion.CERT_V3;
                                certInfo.Issuer = new NATIVE_CRYPTOAPI_BLOB {
                                    cbData = (uint)issuingCertificate.SubjectName.RawData.Length, pbData = issuerDnPtr
                                };
                                certInfo.SignatureAlgorithm = signingAlgorithmIdentifier;
                                certInfo.NotAfter           = FileTimeHelper.ToFileTimeStructureUtc(notAfter ?? DateTime.Now.AddHours(-1).AddYears(5));
                                certInfo.NotBefore          = FileTimeHelper.ToFileTimeStructureUtc(notBefore ?? DateTime.Now.AddHours(-1));
                                certInfo.cExtension         = extensions.Extensions.cExtension;
                                certInfo.rgExtension        = extensions.Extensions.rgExtension;
                                var size           = 0u;
                                var CERT_INFO_TYPE = (IntPtr)2;
                                if (!Crypt32.CryptSignAndEncodeCertificate(signingKey.Handle, signingKey.KeySpec, EncodingType.X509_ASN_ENCODING, CERT_INFO_TYPE, ref certInfo, ref signingSignatureAlgorithmIdentifier, IntPtr.Zero, IntPtr.Zero, ref size))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                var buffer = Marshal.AllocHGlobal((int)size);
                                if (!Crypt32.CryptSignAndEncodeCertificate(signingKey.Handle, signingKey.KeySpec, EncodingType.X509_ASN_ENCODING, CERT_INFO_TYPE, ref certInfo, ref signingSignatureAlgorithmIdentifier, IntPtr.Zero, buffer, ref size))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                const int CERT_KEY_PROV_INFO_PROP_ID = 2;
                                var       certificate = new X509Certificate2(SerializeCertificate(buffer, size));
                                var       keyProvInfo = new CRYPT_KEY_PROV_INFO
                                {
                                    cProvParam        = 0,
                                    dwKeySpec         = privateKey.KeySpec,
                                    dwProvType        = privateKey.Handle.IsNCryptKey ? ProviderType.CNG : ProviderType.PROV_RSA_AES,
                                    pwszProvName      = privateKey.ProviderName,
                                    dwFlags           = 0,
                                    pwszContainerName = privateKey.Name
                                };
                                if (!Crypt32.CertSetCertificateContextProperty(certificate.Handle, CERT_KEY_PROV_INFO_PROP_ID, 0u, ref keyProvInfo))
                                {
                                    throw new Win32Exception(Marshal.GetLastWin32Error());
                                }
                                return(new X509Certificate2(certificate));
                            }
                        }
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(basicEncodedDataPtr);
                    Marshal.FreeHGlobal(certExtensionPtr);
                }
            }
        }
Example #24
0
        private Stream GetDataStream(ReadOnlySpan <byte> sessionData, bool verifyIntegrity)
        {
            PgpSymmetricKeyAlgorithm keyAlgorithm = (PgpSymmetricKeyAlgorithm)sessionData[0];

            if (keyAlgorithm == PgpSymmetricKeyAlgorithm.Null)
            {
                return(inputStream);
            }

            var key = sessionData.Slice(1);
            SymmetricAlgorithm encryptionAlgorithm = PgpUtilities.GetSymmetricAlgorithm(keyAlgorithm);
            var iv = new byte[(encryptionAlgorithm.BlockSize + 7) / 8];

            byte[]           keyArray = Array.Empty <byte>();
            ICryptoTransform decryptor;
            var inlineIv = new byte[iv.Length * 2]; // Aligned to block size

            try
            {
                keyArray  = key.ToArray();
                decryptor = encryptionAlgorithm.CreateDecryptor(keyArray, iv);
                if (encryptedPacket is SymmetricEncDataPacket)
                {
                    if (inputStream.ReadFully(inlineIv.AsSpan(0, iv.Length + 2)) < iv.Length + 2)
                    {
                        throw new EndOfStreamException();
                    }

                    var decryptedInlineIv = decryptor.TransformFinalBlock(inlineIv, 0, inlineIv.Length);
                    if (verifyIntegrity)
                    {
                        VerifyInlineIV(decryptedInlineIv.AsSpan(0, iv.Length), decryptedInlineIv.AsSpan(iv.Length, 2));
                    }

                    // Perform reset according to the OpenPGP CFB rules
                    decryptor = encryptionAlgorithm.CreateDecryptor(keyArray, inlineIv.AsSpan(2, iv.Length).ToArray());
                }
            }
            finally
            {
                CryptographicOperations.ZeroMemory(keyArray.AsSpan());
            }

            encStream = new CryptoStream(
                inputStream,
                new ZeroPaddedCryptoTransform(decryptor),
                CryptoStreamMode.Read);
            if (encryptedPacket is SymmetricEncIntegrityPacket)
            {
                hashAlgorithm          = SHA1.Create();
                tailEndCryptoTransform = new TailEndCryptoTransform(hashAlgorithm, hashAlgorithm.HashSize / 8);
                encStream = new CryptoStream(encStream, tailEndCryptoTransform, CryptoStreamMode.Read);

                if (encStream.ReadFully(inlineIv.AsSpan(0, iv.Length + 2)) < iv.Length + 2)
                {
                    throw new EndOfStreamException();
                }

                if (verifyIntegrity)
                {
                    VerifyInlineIV(inlineIv.AsSpan(0, iv.Length), inlineIv.AsSpan(iv.Length, 2));
                }
            }

            return(encStream);
        }
Example #25
0
 /// <summary>
 /// Get the hash for a file.
 /// </summary>
 /// <param name="hashAlgorithm">The hash algorithm to use.</param>
 /// <param name="fileInfo">The file to hash.</param>
 /// <returns>A string hash.</returns>
 public static string GetHashForFile(HashAlgorithm?hashAlgorithm, FileInfo fileInfo) =>
 GetHash(hashAlgorithm, File.ReadAllText(fileInfo.FullName));