Encryption 从Java到C的RSA签名端口#

Encryption 从Java到C的RSA签名端口#,encryption,rsa,Encryption,Rsa,我有一个Java中的方法,C#中的代码应该是相同的。我正在苦苦思索C#代码将如何实现这一点 私有字符串签名SHA256RSA(字符串输入)引发异常 { 字节[]b1=Base64.getDecoder().decode(privKey); PKCS8EncodedKeySpec spec=新的PKCS8EncodedKeySpec(b1); KeyFactory kf=KeyFactory.getInstance(“RSA”); Signature privateSignature=Signat

我有一个Java中的方法,C#中的代码应该是相同的。我正在苦苦思索C#代码将如何实现这一点

私有字符串签名SHA256RSA(字符串输入)引发异常
{
字节[]b1=Base64.getDecoder().decode(privKey);
PKCS8EncodedKeySpec spec=新的PKCS8EncodedKeySpec(b1);
KeyFactory kf=KeyFactory.getInstance(“RSA”);
Signature privateSignature=Signature.getInstance(“SHA256withRSA”);
privatesign.initSign(kf.generatePrivate(spec));
privatesign.update(input.getBytes(StandardCharsets.UTF_8));
返回byteArrayToHex(privateSignature.sign());
}

使用.NET标准2.1,您需要一个小助手来解码Base64编码的DER文件中的私钥

using System;
using System.Security.Cryptography;
using System.Buffers.Binary;
using System.Text;

namespace Demo
{
    class Program
    {
        const string DerPrivateKey = "MIIBywIBAAJhALkPdKoBJJg8t0Qg7VhyomS+PpKNMzn0NQ/P3zt55uAmLKenUV9xbMhW1SQRUbTEDdDUlfIiBMCzNAxB5od2IrhP4+/nKmUNsIoxOdwL0j//X74xalv9137T+y4ubLzVhwIDAQABAmAScdvq5dpD4ilR/QYq/qH48I1EBhbI+/Id9VYGk4vTY3qn6yFNJfz1qtHrml5OagvbBQLyPwjwxSumkzGelauqr4NvpOirK18v3xzhlsSmys6JZ5nILG16JByXxJjvziECMQDluHUNOCElxIbIrFOTVBaiqs4Iw9b/UJ7Wf7GglFk4pS00wjSnuDMDqGjyb4tgQ3UCMQDOOxdcSs2CPLrppT463NMqDoGide33X4s5y67E9v44IMTKuOwIXoDzgTcoGmeJwYsCMQDWUZRrA93xFXxGRngmsMH5e2+Dv+qbAsVeC35V+XGQJpKZcUKc4348wGdBIA4hfm0CMQCllxDkzDNDFZxHKqVTAiiTpl40olhWvmK+H2vPPztUugsJc34iIi+MVf6BtuHX3I0CMEDuG1uewuwcgHxWTGMnvSqQjkwtTUI0It6c8PTf8URGtoHx7HNl/wKoGGgXLTRY1w==";

        static void Main(string[] args)
        {
            var signature = SignSHA256RSA(base64Key: DerPrivateKey, input: "Hello world!");
            System.Console.WriteLine("Signature (HEX): " + signature);
        }

        private static string SignSHA256RSA(string base64Key, string input)
        {
            // Load key with the little DER helper
            var rsa = LoadRSAKey(derPrivateKey: Convert.FromBase64String(DerPrivateKey));

            // Sign
            var inputBytes = Encoding.UTF8.GetBytes(input);
            var signatureBytes = rsa.SignData(inputBytes, 0, inputBytes.Length, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);

            // Convert signature to hex
            var signatureHex = BitConverter.ToString(signatureBytes).Replace("-", string.Empty);
            return signatureHex;
        }

        private static RSA LoadRSAKey(ReadOnlySpan<byte> derPrivateKey)
        {
            // Expect sequence
            if (AsnHelper.GetTag(derPrivateKey[0]) != 16)
                throw new FormatException($"unexpected tag");

            // Read sequence length
            derPrivateKey = derPrivateKey.Slice(1);
            if (!AsnHelper.TryReadLength(derPrivateKey, out var length, out var bytesRead))
                throw new FormatException($"unexpected length");

            var sequence = AsnHelper.ReadSequence(derPrivateKey.Slice(bytesRead, length));

            // https://www.hanselman.com/blog/DecodingAnSSHKeyFromPEMToBASE64ToHEXToASN1ToPrimeDecimalNumbers.aspx
            var rsaParameters = new RSAParameters
            {
                Modulus = sequence[1].RawData,
                Exponent = sequence[2].RawData,
                D = sequence[3].RawData,
                P = sequence[4].RawData,
                Q = sequence[5].RawData,
                DP = sequence[6].RawData,
                DQ = sequence[7].RawData,
                InverseQ = sequence[8].RawData,
            };

            var rsa = RSA.Create();
            rsa.ImportParameters(rsaParameters);

            return rsa;
        }
    }

    /// <summary>
    /// Quick helper: only works on specific key format
    /// 
    /// https://en.wikipedia.org/wiki/X.690#BER_encoding
    /// </summary>
    internal static class AsnHelper
    {
        public static int GetTag(byte value) => value & 0b11111;

        public static AsnEncodedDataCollection ReadSequence(ReadOnlySpan<byte> source)
        {
            var sequence = new AsnEncodedDataCollection();
            while (!source.IsEmpty)
            {
                var tag = GetTag(source[0]);
                if (tag != 2)
                    throw new FormatException("only support integer");

                source = source.Slice(1);
                if (!TryReadLength(source, out var length, out var bytesRead))
                    throw new FormatException("invalid length");

                source = source.Slice(bytesRead);
                var value = new AsnEncodedData(source.Slice(0, length).ToArray());
                source = source.Slice(length);
                sequence.Add(value);
            }

            return sequence;
        }

        public static bool TryReadLength(ReadOnlySpan<byte> source, out int length, out int bytesRead)
        {
            length = 0;
            bytesRead = 0;
            const byte MultiByteMarker = 0x80;

            bytesRead = 1;
            if ((source[0] & MultiByteMarker) == 0)
            {
                length = source[0];
                return true;
            }
            int lengthLength = source[0] & 0x7F;
            bytesRead += lengthLength;
            if (lengthLength == 2)
            {
                length = BinaryPrimitives.ReadInt16BigEndian(source.Slice(1));
                return true;
            }

            return false;
        }
    }
}


这就是我最终解决这个问题的方法

  • 我使用了这个第三方库 然后我就用了这个代码

准确地指定在c#中要执行的操作。编写一个代码,执行与Java相同的操作,或者您希望验证用Java创建的签名。我不是这两种语言中的加密专家。你的目标是哪个.NET运行时?.NET标准2.1感谢你的评论。实际上,我用另一种方法解决了这个问题,使用第三方Nuget读取PEM文件。我将发布我的完整解决方案
    private static string SignSHA256RSA(string itemToSign)
    {
        var bytes = Encoding.UTF8.GetBytes(itemToSign);
        using (var stream = File.OpenRead(@"C:\PrivateKey.pem"))
        using (var reader = new PemReader(stream))
        {
            var rsaParameters = reader.ReadRsaKey();
            byte[] hv = SHA256.Create().ComputeHash(bytes);
            RSACryptoServiceProvider prov = new RSACryptoServiceProvider();
            RSAParameters rsp = new RSAParameters();
            prov.ImportParameters(rsaParameters);
            RSAPKCS1SignatureFormatter rf = new RSAPKCS1SignatureFormatter(prov);
            rf.SetHashAlgorithm("SHA256");
            byte[] signature = rf.CreateSignature(hv);
            var finalHex = BitConverter.ToString(signature).Replace("-", string.Empty).ToLowerInvariant();
            return finalHex;
        }
    }