开发者社区> 问答> 正文

如何在C#中使用PFX证书签署请求?

我正在尝试利用非官方的API文档。我需要使用自己的证书对所有请求进行签名,但是文档仅提供了要使用的Java代码,如下所示:

public class EncryptionUtils {
private static final String ALGORITHM_NAME = "SHA1withRSA";
private static final String CERT_TYPE = "pkcs12";
private static final String CONTAINER_NAME = "LoginCert";
private static final String PASSWORD = "CE75EA598C7743AD9B0B7328DED85B06";

public static String signContent(byte[] contents, final InputStream cert) throws IOException, GeneralSecurityException, NullPointerException {
    final KeyStore instance = KeyStore.getInstance(CERT_TYPE);
    instance.load(cert, PASSWORD.toCharArray());
    final PrivateKey privateKey = (PrivateKey) instance.getKey(CONTAINER_NAME, PASSWORD.toCharArray());
    final Signature instance2 = Signature.getInstance(ALGORITHM_NAME);
    instance2.initSign(privateKey);
    instance2.update(contents);
    return Base64.getEncoder().encodeToString(instance2.sign());
}}

我想出了这段代码

private static string password = "CE75EA598C7743AD9B0B7328DED85B06";
    public static string Sign(string text, string cert)
    {
        X509Certificate2 certificate = new X509Certificate2(DecodeCrt(cert), password, X509KeyStorageFlags.Exportable);
        RSA provider = (RSA)certificate.PrivateKey;
        // Hash the data
        var hash = HashText(text);
        // Sign the hash

        var signature = provider.SignHash(hash, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
        return Convert.ToBase64String(signature);

    }
    public static byte[] HashText(string text) 
    {
        SHA1Managed sha1Hasher = new SHA1Managed();
        UnicodeEncoding encoding = new UnicodeEncoding();
        byte[] data = encoding.GetBytes(text);
        byte[] hash = sha1Hasher.ComputeHash(data);
        return hash;
    }
    public static byte[] DecodeCrt(string crt)
    {
        return Convert.FromBase64String(crt);
    }

但是输出与Java版本不同。我试图从c#临时运行Java任务,所以我想知道它是否还能工作。有什么办法用C#编写此代码吗?

问题来源:Stack Overflow

展开
收起
montos 2020-03-25 15:17:28 860 0
1 条回答
写回答
取消 提交回答
  • 这两个代码都用于带有Pkcs#1 v1.5填充和SHA1的签名RSA,这在Java代码中通过SHA1withRSA和在RSA#SignHash方法中通过2nd和3rd参数显式地在C#代码中指定。由于签名的Pkcs#1 v1.5变体(RSASSA-PKCS1-v1_5)是确定性的,因此两个代码都必须提供相同的签名(假定要签名的数据相同和私钥相同)。

    如果不是这种情况,实际上只有两种合理的解释:

    • 首先,使用的编码:在Java代码中,数据以形式传输byte[],因此无法根据发布的代码确定使用哪种编码。相反,在C#代码中,数据作为字符串传递并转换为byte[]in HashText。为此,UnicodeEncoding使用了标准代码,它使用UTF16LE和字节顺序标记(BOM)。对于UTF8(无BOM)UTF8Encoding,必须使用。这是至关重要的,同样的编码在C#代码在Java代码中应用,否则不同的签名通常产生。
    • 第二,pfx / p12文件:pfx / p12文件可以包含多个证书。在Java代码中,KeyStore#getKey引用带有别名的私钥(对证书也是如此),在C#代码中,X509Certificate2(Byte[], String, X509KeyStorageFlags)引用容器中的第一个证书,另请参见此处。为了确保在两个代码中引用相同的证书/密钥,pfx / p12文件因此可能仅包含一个包含相应私钥的证书。

    如果考虑到这一点,则这两个代码都会在我的机器上生成相同的签名(假设要签名的数据相同,并且文件pfx / p12相同)。

    最后,应该指出的是,两种代码cert都用于不同的对象。在Java代码中,它表示InputStreamC#代码中的pfx / pf12文件的Base64编码二进制数据。

    回答来源:Stack Overflow

    2020-03-25 15:29:01
    赞同 展开评论 打赏
问答分类:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载

相关实验场景

更多