在UWP中使用基于CMS的格式签名数据

时间:2016-06-14 14:22:43

标签: c# wcf uwp sign pkcs#7

我需要在WCF服务和UWP应用之间传输数据。所以我在收到数据后签名并验证数据。我有个问题。 WCF中签名的数据结果是UWP应用程序的差异。(当然,我无法验证数据)这是我的源代码:

// WCF
private String Sign(string Message)
{
    ContentInfo cont = new ContentInfo(Encoding.UTF8.GetBytes(Message));
    SignedCms signed = new SignedCms(cont, true);
    _SignerCert = new X509Certificate2("Path", "Password");
    CmsSigner signer = new CmsSigner(_SignerCert);
    signer.IncludeOption = X509IncludeOption.None;
    signed.ComputeSignature(signer);
    return Convert.ToBase64String(signed.Encode());
}

//UWP
public static async Task<String> Sign(String Message)
{
    StorageFolder appInstalledFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
    var CerFile = await appInstalledFolder.GetFileAsync(@"Assets\PAYKII_pkcs12.p12");
    var CerBuffer = await FileIO.ReadBufferAsync(CerFile);
    string CerData = CryptographicBuffer.EncodeToBase64String(CerBuffer);

    await CertificateEnrollmentManager.ImportPfxDataAsync
        (CerData, "Password",
        ExportOption.NotExportable,
        KeyProtectionLevel.NoConsent,
        InstallOptions.None,
        "RASKey2");

    var Certificate = (await CertificateStores.FindAllAsync(new CertificateQuery() { FriendlyName = "RASKey2" })).Single();

    IInputStream pdfInputstream;
    InMemoryRandomAccessStream originalData = new InMemoryRandomAccessStream();
    await originalData.WriteAsync(CryptographicBuffer.ConvertStringToBinary(Message,BinaryStringEncoding.Utf8));
    await originalData.FlushAsync();
    pdfInputstream = originalData.GetInputStreamAt(0);
    CmsSignerInfo signer = new CmsSignerInfo();
    signer.Certificate = Certificate;
    signer.HashAlgorithmName = HashAlgorithmNames.Sha1;
    IList<CmsSignerInfo> signers = new List<CmsSignerInfo>();

    signers.Add(signer);

    IBuffer signature = await CmsDetachedSignature.GenerateSignatureAsync(pdfInputstream, signers, null);
    return CryptographicBuffer.EncodeToBase64String(signature);
}

1 个答案:

答案 0 :(得分:1)

我偶然发现了你的帖子,因为我想要实现非常相似的功能:在UWP应用中签名消息并验证我的WCF服务中的签名。阅读http://www.codeproject.com/Tips/679142/How-to-sign-data-with-SignedCMS-and-signature-chec之后,我终于成功了(带有分离的签名,即您需要将原始邮件用于验证):

UWP:

public async static Task<string> Sign(Windows.Security.Cryptography.Certificates.Certificate cert, string messageToSign) {
    var messageBytes = Encoding.UTF8.GetBytes(messageToSign);
    using (var ms = new MemoryStream(messageBytes)) {
        var si = new CmsSignerInfo() {
            Certificate = cert,
            HashAlgorithmName = HashAlgorithmNames.Sha256
        };

        var signature = await CmsDetachedSignature.GenerateSignatureAsync(ms.AsInputStream(), new[] { si }, null);
        return CryptographicBuffer.EncodeToBase64String(signature);
    }
}

WCF:

public static bool Verify(System.Security.Cryptography.X509Certificates.X509Certificate2 cert, string messageToCheck, string signature) {
    var retval = false;

    var ci = new ContentInfo(Encoding.UTF8.GetBytes(messageToCheck));
    var cms = new SignedCms(ci, true);
    cms.Decode(Convert.FromBase64String(signature));

    // Check whether the expected certificate was used for the signature.
    foreach (var s in cms.SignerInfos) {
        if (s.Certificate.Equals(cert)) {
            retval = true;
            break;
        }
    }

    // The following will throw if the signature is invalid.
    cms.CheckSignature(true);

    return retval;
}

我的诀窍是要了解桌面SignedCms需要使用原始内容构建,然后解码签名以执行验证。