1

bouncycastleを使用して小さな認証局を構築しようとしています。

証明書はBouncyCastleを使用して生成され、秘密鍵とともに現在のユーザーの証明書ストアに保存されます。

ただし、セキュリティ上の理由から、キーはエクスポート不可としてマークされています。これを回避するのは簡単ですが、それは追加の障壁になることを意味します。

ここで、新しい証明書に署名する必要がある場合は、証明書の秘密鍵にアクセスする必要があります。私はこのコードを使ってみました:

X509Certificate2 caCert = GetRootKey(); // Fetches the certificate from the store
AsymmetricCipherKeyPair caPrivKey = DotNetUtilities.GetKeyPair(caCert.PrivateKey);

残念ながら、CryptographicExceptionが発生します-秘密鍵がエクスポート不可としてマークされているため、これは私が意図したものです;-)

私の質問は、証明書にアクセスせずに証明書の秘密鍵を使用するにはどうすればよいですか?秘密鍵にアクセスする方法がなければ秘密鍵を保存しても意味がないので、いくつかの重要な点を見逃していると確信しています...

私は今これを何時間も探していますが、stackoverflowやGoogleで何も見つかりません。

私が根本的に間違っていることを誰かに教えてもらえますか?何かに署名する別のアプローチはありますか?!

前もって感謝します!

クリス

4

3 に答える 3

0

簡単な答え:BouncyCastleではありません。

キーをBouncyCastle(またはOpenSSLまたはその他の)ライブラリに入れて、そこから使用することはできません。「エクスポートなし」フラグを回避してエクスポートしない限り、これを行う方法はありません。これは、管理者であり、必要なFuがあれば可能です。

できることは、キーへのCryptoAPIハンドルを取得し、CryptoAPIに署名または暗号化操作を実行するように依頼することです。DotNet暗号クラスはCyptoAPIをカプセル化します。

したがって、基本的に必要なのは、DotNet暗号クラスの使用方法に関するチュートリアルです。多くの例があります。たとえば、このMSDN Magazineの記事には、4分の3ほど下のデジタル署名の例があります。

http://msdn.microsoft.com/en-us/magazine/cc163454.aspx

于 2012-05-17T20:05:52.547 に答える
0

この質問はまさに私が必要としているものですが、答えには機能していないリンクがあります。しばらく検索した後、NCryptライブラリを使用してこの実装を見つけました: https ://github.com/Microsoft/Windows-classic-samples/blob/master/Samples/Win7Samples/security/cryptoapi/CertSign/CPP/Sign.cpp

残念ながら、これはCで記述されていますが、C#の実装が必要です。そこで、マネージドC#コードで使用できるこのC ++ \ CLIラッパー(SignerWrapper.h)を作成しました: https ://github.com/DmitriNymi/StoreCertificateSigner

BouncyCastleで使用するカスタムISignatureFactoryも作成しました。同じリポジトリのPksAsn1SignatureFactory.csを参照してください。カスタムISignerを作成するだけです(私のクラス:PksEcdsaSigner)。

これで、PksAsn1SignatureFactoryをISignatureFactoryとしてBouncyCastleに渡して、新しい証明書を作成できます。たとえば、単体テストPksAsn1SignatureFactoryTest.cs-ISignatureFactoryおよびCertificateIssuerTest.csの明示的な呼び出し-ヘルパークラスを使用して、ストア内の別の証明書から秘密鍵で署名された新しい証明書を作成します。

于 2019-05-03T21:01:41.157 に答える
0

プロジェクトにC++/ CLIを追加したくなかったので、System.Security.Pkcs.SignedCmsを使用して純粋なc#ソリューションを考え出しました。Searcherの回答と同様に、これはBouncyCastleで証明書に署名するために使用できるISignatureFactoryの実装を提供します。

using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Cms;
using Org.BouncyCastle.Crypto;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;

public class WindowsSignatureFactory : ISignatureFactory
{
    public AlgorithmIdentifier Algorithm { get; }
    public X509Certificate2 Cert { get; }

    public object AlgorithmDetails => Algorithm;

    public WindowsSignatureFactory(AlgorithmIdentifier algorithm,
            X509Certificate2 cert)
    {
        Algorithm = algorithm;
        Cert = cert;
    }

    public IStreamCalculator CreateCalculator()
    {
        return new WindowsStreamCalculator(Algorithm, Cert);
    }

    private class WindowsStreamCalculator : IStreamCalculator
    {
        public AlgorithmIdentifier Algorithm { get; }
        public X509Certificate2 Cert { get; }
        private MemoryStream MemoryStream { get; } = new MemoryStream();
        public Stream Stream => MemoryStream;

        public WindowsStreamCalculator(AlgorithmIdentifier algorithm,
                X509Certificate2 cert)
        {
            Algorithm = algorithm;
            Cert = cert;
        }

        public object GetResult()
        {
            var signer = new System.Security.Cryptography.Pkcs.CmsSigner(Cert);
            // This maps e.g. "rsa with sha256" (OID 1.2.840.113549.1.1.11) to
            // "sha256" (OID 2.16.840.1.101.3.4.1)
            var hashAlgorithm = new DefaultDigestAlgorithmIdentifierFinder().find(Algorithm);
            var hashOid = hashAlgorithm.Algorithm.Oid;
            signer.DigestAlgorithm = new System.Security.Cryptography.Oid(hashOid);

            var dataToSign = MemoryStream.ToArray();
            var info = new System.Security.Cryptography.Pkcs.ContentInfo(dataToSign);
            var cms = new System.Security.Cryptography.Pkcs.SignedCms(info, true);
            cms.ComputeSignature(signer, true);

            // This is the tricky part: usually you would call cms.Export() to get a signed
            // message, but we only want the signature
            var cmsSigner = cms.SignerInfos
                .Cast<System.Security.Cryptography.Pkcs.SignerInfo>().ToArray().Single();
            var signatureData = cmsSigner.GetSignature();

            return new SimpleBlockResult(signatureData);
        }
    }
}

次のように、Asn1SignatureFactoryの代わりに使用できます。

public static Org.BouncyCastle.X509.X509Certificate SignCertificate(
        X509V3CertificateGenerator generator,
        X509Certificate2 nonExportableSigningCertificate)
{
    var signer = new WindowsSignatureFactory(
        new AlgorithmIdentifier(X9ObjectIdentifiers.ECDsaWithSha256),
        nonExportableSigningCertificate);

    var signed = generator.Generate(signer);

    // Make sure it worked
    var signingCertBouncy = DotNetUtilities.FromX509Certificate(nonExportableSigningCertificate);
    signed.Verify(signingCertBouncy.GetPublicKey());

    return signed;
}
于 2021-05-11T01:55:10.597 に答える