0

I've been looking to replace some cryptography services that use the standard .NET implementations to the BouncyCastle FIPS C# library. I've got RSA and PSS working but I'm struggling to understand an issue with Elliptical Curve.

As some groundwork and to better understand the library, I set up tests to verify that data signed with the standard .NET implementation can be verified using the FIPS library and that I can correctly load keys from JSON and X5092s.

I can load keys generated into both libraries and sign and verify data using both. However, if I sign something with the .NET implementation, I cannot verify it with the FIPS library, and vice versa.

As far as I can see, I'm not missing any parameters, but my cryptography knowledge is more practical than anything, so I may be missing something.

    [Fact]
    public void SignVerifyWithFipsAndDotNet()
    {
    FipsEC.KeyGenerationParameters originalKeyGenParameters =
        new FipsEC.KeyGenerationParameters(FipsEC.DomainParams.P384);

    FipsEC.KeyPairGenerator originalKpGen =
        CryptoServicesRegistrar.CreateGenerator(originalKeyGenParameters, new SecureRandom());

    var originalEd25519Keys = originalKpGen.GenerateKeyPair();

    var ecParameters = new ECParameters()
    {
        Curve = System.Security.Cryptography.ECCurve.NamedCurves.nistP384,
        Q = new System.Security.Cryptography.ECPoint()
        {
            X = originalEd25519Keys.PublicKey.W.XCoord.GetEncoded(),
            Y = originalEd25519Keys.PublicKey.W.YCoord.GetEncoded()
        },
        D = originalEd25519Keys.PrivateKey.S.ToByteArrayUnsigned()
    };

    // Ensure that the parameters match
    originalEd25519Keys.PrivateKey.S.ToByteArray().Should().BeEquivalentTo(ecParameters.D);
    originalEd25519Keys.PublicKey.W.XCoord.GetEncoded().Should().BeEquivalentTo(ecParameters.Q.X);
    originalEd25519Keys.PublicKey.W.YCoord.GetEncoded().Should().BeEquivalentTo(ecParameters.Q.Y);

    var ecdsa = ECDsa.Create(ecParameters);

    var cert = new CertificateRequest("SN=test", ecdsa, HashAlgorithmName.SHA384)
        .CreateSelfSigned(DateTimeOffset.UtcNow, DateTimeOffset.UtcNow.AddDays(2));

    var message = Encoding.UTF8.GetBytes("Hello, World!");

    // Sign DOTNET
    var dotNetSignature = ecdsa.SignData(message, HashAlgorithmName.SHA384);

    //SIGN FIPS
    var fipsSignature = generateECDSASignature(originalEd25519Keys.PrivateKey, message);

    // Verify Each using own verify method
    cert.GetECDsaPublicKey().VerifyData(message, dotNetSignature, HashAlgorithmName.SHA384).Should().BeTrue();
    verifyECDSASignature(originalEd25519Keys.PublicKey, fipsSignature, message).Should().BeTrue();

    //VERIFY FIPS using DOTNET (FAILS)
    cert.GetECDsaPublicKey().VerifyData(message, fipsSignature, HashAlgorithmName.SHA384).Should().BeTrue();

    //VERIFY DOTNET using FIPS (FAILS)
    verifyECDSASignature(originalEd25519Keys.PublicKey, dotNetSignature, message).Should().BeTrue();
}

public static byte[] generateECDSASignature(AsymmetricECPrivateKey key, byte[] message)
{
    ISignatureFactoryService signatureFactoryProvider =
        CryptoServicesRegistrar.CreateService(key, new SecureRandom());

    ISignatureFactory<FipsEC.SignatureParameters> signer =
        signatureFactoryProvider.CreateSignatureFactory(FipsEC.Dsa.WithDigest(FipsShs.Sha384));

    IStreamCalculator<IBlockResult> calculator = signer.CreateCalculator();
    Stream sOut = calculator.Stream;
    sOut.Write(message, 0, message.Length);
    sOut.Close();
    return calculator.GetResult().Collect(); }

public static bool verifyECDSASignature(AsymmetricECPublicKey key, byte[] signature, byte[] message)
{
    IVerifierFactoryService verifierFactoryProvider = CryptoServicesRegistrar.CreateService(key);

    IVerifierFactory<FipsEC.SignatureParameters> verifier =
        verifierFactoryProvider.CreateVerifierFactory(FipsEC.Dsa.WithDigest(FipsShs.Sha384));

    IStreamCalculator<IVerifier> calculator = verifier.CreateCalculator();

    Stream sOut = calculator.Stream;
    sOut.Write(message, 0, message.Length);
    sOut.Close();
    return calculator.GetResult().IsVerified(signature);
} 

Joe
  • 1

0 Answers0