Xamarin PCLCrypto RSACryptoServiceProvider SignData等效

时间:2017-01-19 21:21:30

标签: c# xamarin cryptography pcl-crypto

我目前正在使用PCLCrypto,并一直在寻找一种模仿System.Security.Cryptography.RSACryptoServiceProvider SignData函数的方法。目前我正在使用此代码创建:

var mac = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithm.RsaSignPkcs1Sha512);            
var cryptoKey = mac.CreateKeyPair(2048);
var hash = WinRTCrypto.CryptographicEngine.Sign(cryptoKey, input);
return WinRTCrypto.CryptographicBuffer.EncodeToBase64String(hash);

这是我用来验证签名的代码:

var mac = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithm.RsaSignPkcs1Sha512);
var keyMaterial = WinRTCrypto.CryptographicBuffer.ConvertStringToBinary(key, Encoding.UTF8);
var cryptoKey = mac.ImportPublicKey(keyMaterial, CryptographicPublicKeyBlobType.X509SubjectPublicKeyInfo);
return WinRTCrypto.CryptographicEngine.VerifySignature(cryptoKey, data, signature);

要清楚,我完全有信心使用正确的密钥对。我的密钥是以下格式:

<RSAKeyValue><Modulus>nMhF8TRjT5O7tTtqr1//9ahokRuNGRxdGwc7fwk+i21Zscr/7L0PlfiE/sTQC/VQrj/BHhkX8CXVMTw1ukSN7zZDD7UCbdvhmV7jhPs/TDJP70Y4pgcG624WnQXjWDgR5f7Mbfg18zsevidtGukK+U5huaBfxhxg2Za3X3JzUYc=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

有人能指出一个产生与RSACryptoServiceProvider相同输出的例子吗?

1 个答案:

答案 0 :(得分:1)

我实际上是自己想出来的,显然它在导入一个以xml格式指定的密钥时遇到了一些问题。我目前的解决方案产生了预期的结果:

    public static class CryptographyExtensions
{
    private static readonly String ModulusStartString = "<Modulus>";
    private static readonly String ModulusEndString = "</Modulus>";
    private static readonly String ExponentStartString = "<Exponent>";
    private static readonly String ExponentEndString = "</Exponent>";
    private static readonly String PStartString = "<P>";
    private static readonly String PEndString = "</P>";
    private static readonly String QStartString = "<Q>";
    private static readonly String QEndString = "</Q>";
    private static readonly String DPStartString = "<DP>";
    private static readonly String DPEndString = "</DP>";
    private static readonly String DQStartString = "<DQ>";
    private static readonly String DQEndString = "</DQ>";
    private static readonly String DStartString = "<D>";
    private static readonly String DEndString = "</D>";
    private static readonly String InverseQStartString = "<InverseQ>";
    private static readonly String InverseQEndString = "</InverseQ>";


    public static RSAParameters ConvertPrivateKeyFromString(String privateKey)
    {
        var rsaparams = new RSAParameters()
        {
            Modulus = Convert.FromBase64String(privateKey.Substring(ModulusStartString, ModulusEndString)),
            Exponent = Convert.FromBase64String(privateKey.Substring(ExponentStartString, ExponentEndString)),
            P = Convert.FromBase64String(privateKey.Substring(PStartString, PEndString)),
            Q = Convert.FromBase64String(privateKey.Substring(QStartString, QEndString)),
            DP = Convert.FromBase64String(privateKey.Substring(DPStartString, DPEndString)),
            DQ = Convert.FromBase64String(privateKey.Substring(DQStartString, DQEndString)),
            D = Convert.FromBase64String(privateKey.Substring(DStartString, DEndString)),
            InverseQ = Convert.FromBase64String(privateKey.Substring(InverseQStartString, InverseQEndString))
        };
        return rsaparams;
    }
    public static RSAParameters ConvertPublicKeyFromString(String publicKey)
    {
        var rsaparams = new RSAParameters()
        {
            Modulus = Convert.FromBase64String(publicKey.Substring(ModulusStartString, ModulusEndString)),
            Exponent = Convert.FromBase64String(publicKey.Substring(ExponentStartString, ExponentEndString))
        };
        return rsaparams;
    }

public static class RsaEncryption
{
    public static string HashAndSign(byte[] input, string key)
    {
        var mac = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithm.RsaSignPkcs1Sha512);
        var cryptoKey = mac.ImportParameters(CryptographyExtensions.ConvertPrivateKeyFromString(key));
        var hash = WinRTCrypto.CryptographicEngine.Sign(cryptoKey, input);
        return WinRTCrypto.CryptographicBuffer.EncodeToBase64String(hash);
    }

    public static bool VerifySignature(byte[] data, byte[] signature, string key)
    {
        var mac = WinRTCrypto.AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithm.RsaSignPkcs1Sha512);
        var cryptoKey = mac.ImportParameters(CryptographyExtensions.ConvertPublicKeyFromString(key));
        return WinRTCrypto.CryptographicEngine.VerifySignature(cryptoKey, data, signature);
    }
}
public static class StringExtensions
{
    public static string Substring(this string @this, string from = null, string until = null, StringComparison comparison = StringComparison.OrdinalIgnoreCase)
    {
        var fromLength = (from ?? string.Empty).Length;
        var startIndex = !string.IsNullOrEmpty(from)
            ? @this.IndexOf(from, comparison) + fromLength
            : 0;

        if (startIndex < fromLength) { throw new ArgumentException("from: Failed to find an instance of the first anchor"); }

        var endIndex = !string.IsNullOrEmpty(until)
        ? @this.IndexOf(until, startIndex, comparison)
        : @this.Length;

        if (endIndex < 0) { throw new ArgumentException("until: Failed to find an instance of the last anchor"); }

        var subString = @this.Substring(startIndex, endIndex - startIndex);
        return subString;
    }
}