bbr*_*own 8 c# iphone encryption rsa
到目前为止,我已经花了两天时间来处理这个问题,并且可以根据我的需要进行梳理,所以这是最后的选择.
我有一个X509证书,其公钥存储在iPhone的钥匙串中(此时仅为模拟器).在ASP.NET方面,我在证书库中获得了带有私钥的证书.当我在iPhone上加密字符串并在服务器上解密时,我收到CryptographicException"错误的数据".我尝试了Array.Reverse在RSACryptoServiceProvider页面上建议的远景,但它没有帮助.
我比较了两侧的64弦,它们是相同的.我在解码后比较了原始字节数组,它们也相等.如果我使用公钥在服务器上加密,则字节数组与iPhone的版本不同,并且可以使用私钥轻松解密.原始明文字符串是115个字符,因此它在我的2048位密钥的256字节限制范围内.
这是iPhone加密方法(几乎是CryptoExercise示例应用程序的wrapSymmetricKey方法):
+ (NSData *)encrypt:(NSString *)plainText usingKey:(SecKeyRef)key error:(NSError **)err
{
size_t cipherBufferSize = SecKeyGetBlockSize(key);
uint8_t *cipherBuffer = NULL;
cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
memset((void *)cipherBuffer, 0x0, cipherBufferSize);
NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];
OSStatus status = SecKeyEncrypt(key, kSecPaddingNone,
(const uint8_t *)[plainTextBytes bytes],
[plainTextBytes length], cipherBuffer,
&cipherBufferSize);
if (status == noErr)
{
NSData *encryptedBytes = [[[NSData alloc]
initWithBytes:(const void *)cipherBuffer
length:cipherBufferSize] autorelease];
if (cipherBuffer)
{
free(cipherBuffer);
}
NSLog(@"Encrypted text (%d bytes): %@",
[encryptedBytes length], [encryptedBytes description]);
return encryptedBytes;
}
else
{
*err = [NSError errorWithDomain:@"errorDomain" code:status userInfo:nil];
NSLog(@"encrypt:usingKey: Error: %d", status);
return nil;
}
}
Run Code Online (Sandbox Code Playgroud)
这是服务器端C#解密方法:
private string Decrypt(string cipherText)
{
if (clientCert == null)
{
// Get certificate
var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
foreach (var certificate in store.Certificates)
{
if (certificate.GetNameInfo(X509NameType.SimpleName, false) == CERT)
{
clientCert = certificate;
break;
}
}
}
using (var rsa = (RSACryptoServiceProvider)clientCert.PrivateKey)
{
try
{
var encryptedBytes = Convert.FromBase64String(cipherText);
var decryptedBytes = rsa.Decrypt(encryptedBytes, false);
var plaintext = Encoding.UTF8.GetString(decryptedBytes);
return plaintext;
}
catch (CryptographicException e)
{
throw(new ApplicationException("Unable to decrypt payload.", e));
}
}
}
Run Code Online (Sandbox Code Playgroud)
我怀疑平台之间存在一些编码问题.我知道一个是大端,另一个是小端,但我不知道哪个是哪个或如何克服差异.Mac OS X,Windows和iPhone都是小端的,所以这不是问题所在.
新理论:如果将OAEP填充布尔值设置为false,则默认为PKCS#1 1.5填充.显然,SecKey只有SecPadding定义PKCS1,PKCS1MD2,PKCS1MD5,和PKCS1SHA1.也许微软的PKCS#1 1.5!= Apple的PKCS1,因此填充正在影响加密的二进制输出.我尝试使用kSecPaddingPKCS1与fOAEP设置为false,它仍然没有工作.kSecPaddingPKCS1是等效于PKCS#1 1.5.回到理论上的绘图板......
其他新尝试的理论:
成功!
事实证明,我在iPhone模拟器上的钥匙扣中有一些瑕疵,可以说是混淆了水域.我删除了Keychain DB,~/Library/Application Support/iPhone Simulator/User/Library/Keychains/keychain-2-debug.db使其重新创建,并且工作正常.谢谢你的帮助.数字本来是简单但不明显的.(我学到的两件事:1)从模拟器中卸载应用程序不会清除其Keychain条目,2)定期开始绝对新鲜.)
注意:keychain文件的通用路径取决于iOS版本:〜/ Library/Application Support/iPhone Simulator/[version] /Library/Keychains/keychain-2-debug.db eg~/Library/Application Support/iPhone模拟器/ 4.3 /库/钥匙串/ keychain-2-debug.db
嗯...第一步(正如您所说的那样)是使用 iPhone 和 C# 实现使用相同的初始化向量来加密相同的消息。您应该得到相同的输出。你说你没有,所以有问题。
这意味着:
我建议前两种可能性不大,但可能性很小。
您声明:“在不同的证书存储中安装了 .cer 文件,并且服务器加密的字符串往返得很好”...这并不能证明任何事情:所有这些证明的是,给定一组特定的随机数字,您可以成功加密/解密一个平台。您不能保证两个平台都看到相同的随机数集。
所以我建议你把它降到尽可能低的水平。检查两个平台上加密的直接(字节数组)输入和输出。如果使用完全相同的(二进制)输入,您没有得到相同的输出,那么您就会遇到平台问题。我认为这不太可能,所以我猜你会发现 IV 的解释不同。
| 归档时间: |
|
| 查看次数: |
5127 次 |
| 最近记录: |