问题
I need to transfer data between WCF service and UWP app. So I sign and verify data after receive data. I have a problem. The signed data result in WCF is differences in UWP app.(Of course, I can't verify data) This is my source code:
// 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());
}
and
//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:
I stumbled over your post, because I wanted to achieve something very similar: sign a message in an UWP app and verifying the signature in my WCF Service. After reading http://www.codeproject.com/Tips/679142/How-to-sign-data-with-SignedCMS-and-signature-chec, I finally managed to make this fly (with a detached signature, ie you need to have the original message for verification):
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;
}
The trick for me was to understand that the desktop SignedCms
needs to be constructed with the original content and then decode the signature to perform the verification.
来源:https://stackoverflow.com/questions/37814759/sign-data-using-cms-based-format-in-uwp