Tôi đã dành hai ngày cho đến nay và chải kỹ mọi nguồn theo ý của tôi, vì vậy đây là phương sách cuối cùng.Gặp sự cố khi giải mã trong C# một cái gì đó được mã hóa trên iPhone bằng RSA
Tôi có chứng chỉ X509 có khóa công khai tôi đã lưu trữ trong keychain của iPhone (chỉ mô phỏng tại thời điểm này). Về phía ASP.NET, tôi đã có chứng chỉ trong cửa hàng cert với một khóa riêng. Khi tôi mã hóa một chuỗi trên iPhone và giải mã nó trên máy chủ, tôi nhận được CryptographicException
"Dữ liệu không hợp lệ". Tôi đã thử các Array.Reverse
đề nghị trong trang RSACryptoServiceProvider
trên một longshot, nhưng nó đã không giúp đỡ.
Tôi đã so sánh các chuỗi base-64 ở cả hai bên và chúng bằng nhau. Tôi đã so sánh các mảng byte thô sau khi giải mã và chúng cũng bằng nhau. Nếu tôi mã hóa trên máy chủ bằng cách sử dụng khóa công khai, mảng byte khác với phiên bản của iPhone và dễ dàng giải mã bằng khóa riêng. Chuỗi thô thô là 115 ký tự vì vậy nó nằm trong giới hạn 256 byte của khóa 2048-bit của tôi.
Dưới đây là các phương pháp mã hóa iPhone (khá nhiều nguyên văn từ wrapSymmetricKey
phương pháp 's CryptoExercise sample app):
+ (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;
}
}
Và đây là server-side phương pháp C# giải mã:
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));
}
}
}
nghi ngờ của tôi là đã có một số vấn đề về mã hóa giữa các nền tảng.
Tôi biết rằng một người là người lớn tuổi và người kia là người ít tuổi nhưng tôi không biết đủ để nói cái nào hay cách nào để khắc phục sự khác biệt.
Hệ điều hành Mac OS X, Windows và iPhone đều là một chút nhỏ bé nên không phải là vấn đề.
Lý thuyết mới: nếu bạn đặt đệm OAEP Boolean thành false, đệm mặc định là đệm PKCS # 1 1.5.
Rõ ràng, SecKey
chỉ có định nghĩa
SecPadding
của
PKCS1
,
PKCS1MD2
,
PKCS1MD5
và
PKCS1SHA1
. Có lẽ PKCS # 1 của Microsoft! = PKCS1 của Apple và do đó padding ảnh hưởng đến đầu ra nhị phân của mã hóa. Tôi đã thử sử dụng
kSecPaddingPKCS1
với
fOAEP
được đặt thành
false
và nó vẫn không hoạt động.
kSecPaddingPKCS1
là equivalent tới PKCS # 1 1.5. Quay lại bảng vẽ về lý thuyết & hellip;
lý thuyết khác mới thử:
- Giấy chứng nhận trên iPhone (file cer) không phải là chính xác giống như các PKCS # 12 bó trên máy chủ (file pfx) và vì vậy nó không bao giờ có thể làm việc. Tệp .cer được cài đặt trong kho lưu trữ cert khác nhau và chuỗi được mã hóa máy chủ được làm tròn tốt;
- Chuyển đổi thành cơ sở 64 và hành động POST thành máy chủ dẫn đến sự kỳ quặc không có trong cùng một lớp, vì vậy tôi đã thử một số URLEncoding/Decoding và sau đó đăng nhị phân thô từ iPhone, xác minh rằng nó bằng nhau và có cùng dữ liệu xấu;
- Chuỗi gốc của tôi là 125 byte vì vậy tôi nghĩ rằng nó có thể cắt ngắn trong UTF-8 (ảnh dài) vì vậy tôi đã cắt nó xuống chuỗi 44 byte mà không có kết quả;
- Nhìn lại thư viện System.Cryptography để đảm bảo rằng tôi đang sử dụng một lớp thích hợp và phát hiện ra `RSAPKCS1KeyExchangeDeformatter`, trở nên phấn khởi với triển vọng mới, và bị từ chối khi nó hoạt động giống hệt nhau.
Thành công!
Hóa ra là tôi đã có một số chiếc cruft trong Keychain của mình trên Trình mô phỏng iPhone đang làm ngập nước, vì vậy để nói. Tôi đã xóa Keychain DB tại ~/Library/Application Support/iPhone Simulator/User/Library/Keychains/keychain-2-debug.db
để làm cho nó được tái tạo và nó hoạt động tốt. Cảm ơn vì tất cả sự giúp đỡ của bạn. Số liệu nó sẽ là một cái gì đó đơn giản nhưng không rõ ràng. (Hai điều tôi đã học được: 1) gỡ cài đặt ứng dụng khỏi trình mô phỏng không xóa các mục Keychain và 2) bắt đầu hoàn toàn mới định kỳ.)
LƯU Ý: Đường dẫn chung cho tệp keychain phụ thuộc vào phiên bản iOS: ~/Library/Application Support/iPhone Simulator/[phiên bản] /Library/Keychains/keychain-2-debug.db ví dụ: ~/Library/Application Support/iPhone Simulator/4.3/Library/Keychains/keychain-2-debug .db
Thời gian để nhận tiền thưởng! – bbrown