我试图在Win 8 Metro应用程序和RESTful WCF服务之间传递一些加密数据.最初Metro应用程序请求公钥,WCF服务将其作为原始流返回,以避免任何讨厌的格式问题. Base 64编码的公钥在metro应用程序中解码为字节数组.这是问题发生的地方.当我试图调用AsymmetricKeyAlgorithmProvider.ImportPublicKey时,我收到错误“ASN1错误标记值已满足”.
我使用RSA PKCS1进行加密.这是相关代码:
WCF服务
string keyName = "This is passed in via a parameter"; var key = !CngKey.Exists(keyName) ? CngKey.Create(CngAlgorithm2.Rsa,keyName) : CngKey.Open(keyName); // Create the RSA container to get keys and then dispose using (var rsaCng = new RSACng(key) { EncryptionPaddingMode = AsymmetricPaddingMode.Pkcs1,KeySize = 2048 }) { byte[] publicBlob = rsaCng.Key.Export(CngKeyBlobFormat.GenericpublicBlob); publicKey = Convert.ToBase64String(publicBlob); }
Metro App
public static string Encrypt(IBuffer dataBuffer,string publicKeyString) { var asymmAlg = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); // The next line fails with ASN1 bad tag value met var publicKey = asymmAlg.ImportPublicKey(CryptographicBuffer.DecodeFromBase64String(publicKeyString),CryptographicpublicKeyBlobType.Pkcs1RsaPublicKey); var encryptedData = CryptographicEngine.Encrypt(publicKey,dataBuffer,null); return CryptographicBuffer.EncodeToBase64String(encryptedData); }
编辑1:以下更多信息
从WCF服务从2048位密钥对导出公钥会产生283位长的密钥blob,而从Metro应用程序导出相同类型的公钥只有270位.当我导入Metro生成的公钥时,它成功.知道为什么WCF服务在其公钥上有13个额外位吗?我认为那些额外的13位导致失败.
以下是产生较短公钥blob的Metro代码:
var provider = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); CryptographicKey standardKeyPair = provider.CreateKeyPair(2048); byte[] standardKey = standardKeyPair.ExportPublicKey(CryptographicpublicKeyBlobType.Pkcs1RsaPublicKey).ToArray();
解决方法
很晚,但也许它会帮助你或节省一些人的时间……
导入期间更改blob类型的类型.这真的很奇怪,但经过实验,我取得了成功.
您在WCF中的代码可能保持不变.
只更改Metro代码:
public static string Encrypt(IBuffer dataBuffer,string publicKeyString) { var asymmAlg = AsymmetricKeyAlgorithmProvider.OpenAlgorithm(AsymmetricAlgorithmNames.RsaPkcs1); // The next line fails with ASN1 bad tag value met var publicKey = asymmAlg.ImportPublicKey(CryptographicBuffer.DecodeFromBase64String(publicKeyString),CryptographicpublicKeyBlobType.BCryptPublicKey); var encryptedData = CryptographicEngine.Encrypt(publicKey,null); return CryptographicBuffer.EncodeToBase64String(encryptedData); }
所以这里唯一的变化是导入过程中的BCryptPublicKey.然后它工作.但不要问我为什么:-).