2009-07-15 19 views
8

का उपयोग कर आईफोन पर एन्क्रिप्टेड कुछ सी # में डिक्रिप्ट करने में समस्या होने के कारण मैंने इस पर दो दिन बिताए हैं और मेरे निपटारे में हर स्रोत के माध्यम से काम किया है, इसलिए यह अंतिम उपाय है।आरएसए

मेरे पास एक एक्स 50 9 प्रमाण पत्र है जिसका सार्वजनिक कुंजी मैंने आईफोन की कीचेन (केवल इस बिंदु पर सिम्युलेटर) में संग्रहीत किया है। एएसपी.नेट पक्ष पर, मुझे प्रमाण पत्र में एक निजी कुंजी के साथ प्रमाण पत्र मिला है। जब मैं आईफोन पर एक स्ट्रिंग एन्क्रिप्ट करता हूं और इसे सर्वर पर डिक्रिप्ट करता हूं, तो मुझे CryptographicException "खराब डेटा" मिलता है। मैंने Array.Reverse को RSACryptoServiceProvider पृष्ठ में लंबे समय तक सुझाए गए प्रयासों की कोशिश की, लेकिन इससे मदद नहीं मिली।

मैंने दोनों तरफ बेस -64 स्ट्रिंग की तुलना की है और वे बराबर हैं। मैंने डीकोडिंग के बाद कच्चे बाइट एरे की तुलना की है और वे भी बराबर हैं। अगर मैं सार्वजनिक कुंजी का उपयोग कर सर्वर पर एन्क्रिप्ट करता हूं, तो बाइट सरणी आईफोन के संस्करण से अलग है और निजी कुंजी का उपयोग करके आसानी से डिक्रिप्ट करता है। कच्ची सादा पाठ स्ट्रिंग 115 वर्ण है, इसलिए यह मेरी 2048-बिट कुंजी की 256-बाइट सीमा के भीतर है।

यहाँ iPhone एन्क्रिप्शन विधि (काफी CryptoExercise sample app के 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; 
    } 
} 

और यहाँ सर्वर साइड सी # डिक्रिप्शन विधि है:

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)); 
     } 
    } 
} 

मेरे संदेह है कि था प्लेटफार्मों के बीच कुछ एन्कोडिंग समस्याएं थीं। मुझे पता है कि एक बड़ा एंडियन है और दूसरा छोटा-प्यारा है लेकिन मुझे यह जानने के लिए पर्याप्त नहीं पता कि कौन सा है या अंतर को कैसे दूर किया जाए। मैक ओएस एक्स, विंडोज़, और आईफोन सभी छोटे-एंडियन हैं इसलिए समस्या नहीं है।

नया सिद्धांत: यदि आप ओएईपी पैडिंग बूलियन को झूठी पर सेट करते हैं, तो यह पीकेसीएस # 1 1.5 पैडिंग पर डिफ़ॉल्ट होता है। SecKey में केवल SecPadding PKCS1, PKCS1MD2, PKCS1MD5, और PKCS1SHA1 की परिभाषाएं हैं। शायद माइक्रोसॉफ्ट के पीकेसीएस # 1 1.5! = ऐप्पल के पीकेसीएस 1 और इसलिए पैडिंग एन्क्रिप्शन के बाइनरी आउटपुट को प्रभावित कर रहा है। मैंने kSecPaddingPKCS1 का उपयोग fOAEP false पर सेट करने का प्रयास किया और यह अभी भी काम नहीं कर रहा है। जाहिर है, kSecPaddingPKCS1equivalent पीकेसीएस # 1 1.5 के लिए है। सिद्धांतों और नरक पर ड्राइंग बोर्ड पर वापस;

अन्य नव कोशिश की सिद्धांत:

  1. प्रमाणपत्र iPhone (.cer फ़ाइल) पर वास्तव में PKCS सर्वर (.pfx फ़ाइल) और इसलिए यह काम नहीं कर सकता था पर # 12 बंडल के रूप में समान नहीं है। विभिन्न प्रमाणपत्र स्टोर में स्थापित .cer फ़ाइल और सर्वर-एन्क्रिप्टेड स्ट्रिंग राउंडट्रिप बस ठीक है; आधार -64
  2. रूपांतरण करने के लिए और सर्वर पर पोस्ट करने का कार्य विचित्रता में हुई है कि एक ही कक्षा गोल यात्रा में मौजूद तो मैं पहले कुछ URLEncoding/डिकोडिंग करने की कोशिश की और फिर iPhone से कच्चे बाइनरी पोस्ट सत्यापित है कि यह बराबर था, नहीं था और एक ही खराब डेटा मिला;
  3. मेरी मूल स्ट्रिंग 125 बाइट्स थी इसलिए मैंने सोचा कि यह यूटीएफ -8 (लंबे शॉट) में छंटनी हो सकती है, इसलिए मैंने इसे 44-बाइट स्ट्रिंग में बिना किसी परिणाम के फसल कर दिया;
  4. सिस्टम पर वापस देखा गया। क्रिप्टोग्राफी लाइब्रेरी यह सुनिश्चित करने के लिए कि मैं एक उचित वर्ग का उपयोग कर रहा हूं और 'आरएसएपीकेसीएस 1 केई एक्सचेंज डिफॉर्मेटर' की खोज की, नई संभावनाओं पर उत्साहित हो गया, और जब यह बिल्कुल वही व्यवहार करता था तो निराश हो गया।

सफलता!

यह पता चला कि आईफोन सिम्युलेटर पर मेरे कीचेन में कुछ क्रूर था जो पानी को हल कर रहा था, इसलिए बोलने के लिए। मैंने ~/Library/Application Support/iPhone Simulator/User/Library/Keychains/keychain-2-debug.db पर कीचेन डीबी को फिर से बनाया जाने के कारण हटा दिया और यह ठीक काम किया। आपकी सारी मदद के लिए शुक्रिया। आंकड़े यह कुछ सरल लेकिन गैर स्पष्ट हो गया होता। (दो बातें मुझे पता चला: 1) सिम्युलेटर से एप्लिकेशन की स्थापना रद्द अपने कीचेन प्रविष्टियों स्पष्ट नहीं है और 2) समय-समय पर पूरी तरह से नई शुरुआत)

नोट:। कीचेन फ़ाइल के लिए जेनेरिक पथ iOS संस्करण पर निर्भर है: ~/Library/अनुप्रयोग समर्थन/iPhone सिम्युलेटर/[संस्करण] /Library/Keychains/keychain-2-debug.db जैसे, ~/Library/अनुप्रयोग समर्थन/iPhone सिम्युलेटर/4.3/Library/Keychains/कीचेन-2-डिबग .db

+0

एक उपहार के लिए समय! – bbrown

उत्तर

3

अच्छा ... पहला कदम (जैसा कि आप कहते हैं कि आपने किया है) उसी संदेश को उसी प्रारंभिक वैक्टर के साथ एन्क्रिप्ट करना है जो आईफोन और सी # कार्यान्वयन दोनों का उपयोग कर रहा है। आपको एक ही आउटपुट मिलना चाहिए। आपने कहा कि आपने नहीं किया, इसलिए एक समस्या है।

इसका मतलब यह है या तो:

  • आरएसए के iPhone कार्यान्वयन सही नहीं है।
  • आरएसए का .NET कार्यान्वयन गलत है।
  • महत्वपूर्ण फाइलों को अलग हैं (या अलग ढंग से व्याख्या की जा रहा है)।

मैं सुझाव दूंगा कि पहले दो असंभव हैं, हालांकि वे दूरस्थ रूप से संभव हैं।

आप कहते हैं: "विभिन्न प्रमाणपत्र स्टोर और सर्वर-एन्क्रिप्टेड स्ट्रिंग में स्थापित .cer फ़ाइल बस ठीक है" ... यह कुछ भी साबित नहीं करता है: यह सब साबित करता है कि संख्याओं का एक विशेष यादृच्छिक सेट दिया गया है जिसे आप एन्क्रिप्ट कर सकते हैं/एक मंच पर सफलतापूर्वक डिक्रिप्ट करें। आप गारंटी नहीं दे रहे हैं कि दोनों प्लेटफॉर्म यादृच्छिक संख्याओं का एक ही सेट देख रहे हैं।

तो मेरा सुझाव है कि आप इसे यहां निम्नतम स्तर पर ले जाएं। दोनों प्लेटफार्मों पर एन्क्रिप्शन के प्रत्यक्ष (बाइट सरणी) इनपुट और आउटपुट का निरीक्षण करें। यदि सटीक (बाइनरी) इनपुट के साथ आपको एक ही आउटपुट नहीं मिलता है, तो आपके पास प्लेटफ़ॉर्म समस्या है। मुझे लगता है कि यह असंभव है, इसलिए मुझे लगता है कि आप पाएंगे कि चतुर्थों का अलग-अलग व्याख्या किया जा रहा है।

+0

आपकी प्रतिक्रिया के लिए धन्यवाद! मैं .NET या कोको पुस्तकालयों में कहीं भी नहीं ढूंढ सकता जहां आप आरएसए एन्क्रिप्शन या डिक्रिप्शन के लिए IV सेट कर सकते हैं। मैंने सोचा कि चतुर्थ केवल सममित एल्गोरिदम पर लागू होता है। मैं भी यह सोचने के लिए नहीं सोचूंगा कि या तो 1 या 2 संभव है, लेकिन मैं यह भी नहीं समझ सकता कि X509 प्रमाणपत्र की सार्वजनिक कुंजी को दो प्लेटफार्मों पर अलग-अलग व्याख्या किया जाएगा। लेकिन मैंने फोन से प्रमाण लिया और इसे सर्वर में फिसल गया और यह वहां सफल रहा, इसलिए मुझे नहीं पता कि क्या सोचना है। मैं यह सुनिश्चित करने के लिए प्रत्येक प्लेटफॉर्म के भीतर सार्वजनिक कुंजी विवरणों को देखूंगा कि वे वही हैं, bbrown

+0

लेकिन मुझे पूरा यकीन है कि मुझे आश्चर्य नहीं होना चाहिए कि एक ही सार्वजनिक कुंजी उसी के लिए अलग-अलग आउटपुट उत्पन्न कर सकती है विभिन्न पास पर इनपुट। यह पीकेसीएस # 1 पैडिंग का उद्देश्य है, कुछ ऐप्पल इंजीनियर ने पुष्टि की: http://lists.apple.com/archives/apple-cdsa/2009/Jul/msg00032.html – bbrown

+0

क्षमा करें - जब मैंने कहा कि चौथा मैं था शायद शब्दावली का दुरुपयोग - यह देर हो चुकी है :) मेरा मतलब मूल रूप से एन्क्रिप्शन कुंजी था: डेटा को आप .NET में ExportParameters विधि से प्राप्त करते हैं या आईफोन पर आपके 'कुंजी' पैरामीटर की सामग्री। मुझे लगता है कि यह सुनिश्चित करने योग्य होगा कि वे वही हैं (पाठ्यक्रम के निजी हिस्से को छोड़कर)। –

-2

मेरा मानना ​​है कि आपने स्वयं को प्रश्न का उत्तर दिया है। समस्या निश्चित रूप से अंतहीनता के भीतर निहित है।

short convert_short(short in) 
{ 
short out; 
char *p_in = (char *) ∈ 
char *p_out = (char *) &out; 
p_out[0] = p_in[1]; 
p_out[1] = p_in[0]; 
return out; 
} 

long convert_long(long in) 
{ 
long out; 
char *p_in = (char *) ∈ 
char *p_out = (char *) &out; 
p_out[0] = p_in[3]; 
p_out[1] = p_in[2]; 
p_out[2] = p_in[1]; 
p_out[3] = p_in[0]; 
return out; 
} 

यह एक अच्छा आप के लिए संसाधन (विकिपीडिया के अलावा अन्य) हो सकता है::

यह दो तरह से रूपांतरण तरीकों लेखन की एक संभव तरीका है http://betterexplained.com/articles/understanding-big-and-little-endian-byte-order/

+0

यह सुनकर बहुत अच्छा है और प्रतिक्रिया के लिए धन्यवाद! मेरी अज्ञानता को क्षमा करें, लेकिन मैं इन रूपांतरण विधियों का उपयोग कैसे करूँगा? मुझे लगता है कि वे आईफोन पर हैं इसलिए मैं इसे अपनी विधि में कहां प्लग करूंगा? – bbrown

+0

यह पता चला है कि प्लेटफार्मों के बीच गतिशीलता पावरपीसी दिनों का एक अवशेष है। मैक ओएस एक्स, x86 आर्किटेक्चर पर आधारित है, विंडोज़ के समान ही छोटा-अंत है। आईआरएम आर्किटेक्चर पर आईफोन भी उतना ही छोटा अंत है जितना मैं खोजों से निर्धारित कर सकता हूं। – bbrown

+0

एंडियननेस यहां कोई समस्या नहीं होगी, वैसे भी। आपके सभी परिचालनों में कच्चे बाइट शामिल हैं, बहु-बाइट संख्या नहीं। –

-3

क्योंकि आप दोनों पक्षों को नियंत्रित, मेरे सिफारिश (यदि आप पुस्तकालय एन्क्रिप्शन एल्गोरिदम दो प्लेटफार्मों पर एक साथ काम करने के लिए नहीं मिल सकता है) दोनों पक्षों पर एन्क्रिप्शन अपने आप को लिखने के लिए, एक ही कलन विधि का उपयोग किया जाएगा।

इस तरह आपके पास नियंत्रण है, और यह देखने के लिए कि क्या गलत हो रहा है, एन्क्रिप्शन आंतरिक को डीबग करने में सक्षम होगा।

यह (बेशक) एक अंतिम उपाय है, लेकिन शायद तीन दिनों कि आप पहले से ही खर्च किया है की तुलना में कम समय ले लिया होता, और सफलता का एक उच्च मौका है

HTH

+4

सभी उचित सम्मान के साथ, मुझे लगता है कि मुझे अपने स्वयं के रोलिंग के बजाय संबंधित ढांचे की सुरक्षा सुविधाओं का उपयोग करना चाहिए। सबसे पहले, उनका कार्यान्वयन युद्ध परीक्षण है और सुरक्षा समीक्षा पास कर दी है कि मेरे पास नहीं होगा। दूसरा, मैं एक सी # और उद्देश्य-सी प्रोग्रामर हूं जो स्वीकार्य रूप से सीमित क्रिप्टोग्राफिक कौशल के साथ है। तीसरा, मुझे लगता है कि मैं इस पर वास्तव में करीब हूं और समस्या घुलनशील है। अंत में, इस स्थिति के बारे में SO (और अन्यत्र) पर प्रश्नों की संख्या से पता चलता है कि बहुत से लोग असफल हो गए हैं और इसलिए एक प्रस्ताव उपलब्ध होना अच्छा लगेगा। – bbrown

+5

उम, नहीं। उनके दाहिने दिमाग में कोई भी आरएसए एल्गोरिदम लागू नहीं कर रहा है जब तक कि (ए) पहले से ही मंच के लिए कोई उपलब्ध नहीं है, (बी) वे एक पेशेवर, अनुभवी क्रिप्टोग्राफर हैं, और (सी) वे बहुत समय व्यतीत करने के इच्छुक हैं कोड समीक्षा और परीक्षण। क्रिप्टोग्राफिक कार्यान्वयन जटिल हैं, सूक्ष्म समस्याओं से ग्रस्त हैं, और बहुत संवेदनशील हैं क्योंकि लोग सक्रिय रूप से शोषण की तलाश में उन पर हमला करेंगे। –

0

क्या यह आपकी मदद ?

Asymmetric Key Encryption w/ .NET & C#

  • कम पद, समय की कमी और सभी के लिए क्षमा करें। वैसे भी, मदद के लिए अपने ट्विटर अनुरोध को देखा .. यह दिखाता है कि मैंने PHP के साथ ऐसा कैसे किया और .NET, simliar पर डिक्रिप्ट किया। मैं नोटिस अपने डिक्रिप्ट वर्ग खान की तुलना में थोड़ा अंतर है, इसलिए इस लेख मदद कर सकता है।
+0

अफसोस की बात है, ओपनएसएसएल आईफोन पर उपलब्ध नहीं है, इसलिए यह मेरी मदद नहीं करता है। लेकिन कोशिश करने के लिए धन्यवाद! – bbrown

+0

जो बिंदु मैं बना रहा था वह मेरा मिलान करने के लिए डिक्रिप्शन दिनचर्या का प्रयास करना था।मैंने पाया कि 50 9 प्रमाणपत्र 2 बेहतर था। –

+0

यह मेरा बुरा था। उपरोक्त कोड नमूने में, "क्लाइंटक्रर्ट" नामक एक निजी इंस्टेंस वैरिएबल है जो X509Certificate2 प्रकार है। मैं इसे लिस्टिंग में शामिल करने में विफल रहा। इसके बारे में क्षमा करें ... – bbrown

1

यह स्टैक ओवरफ्लो पर मेरा पहला जवाब है, इसलिए अगर मैं गलत करता हूं तो कृपया मुझे क्षमा करें!

मैं आपको पूरा जवाब नहीं दे सकता, हालांकि जब मैंने PHP के साथ एकीकृत करने की कोशिश की तो मुझे बहुत ही समान समस्याएं थीं - ऐसा लगता है कि ऐप्पल की प्रमाणपत्र फाइलों का प्रारूप थोड़ा अलग है जो अन्य सॉफ़्टवेयर की अपेक्षा करता है (openssl सहित))।

यहाँ कैसे मैं PHP में एक एन्क्रिप्टेड हस्ताक्षर डिक्रिप्ट है - मैं वास्तव में मापांक और प्रेषित सार्वजनिक कुंजी से पी मैन्युअल निकालने और का उपयोग करें कि आरएसए सामान के लिए है, न कि कुंजी आयात करने की कोशिश की तुलना में:

// Public key format in hex (2 hex chars = 1 byte): 
//30480241009b63495644db055437602b983f9a9e63d9af2540653ee91828483c7e302348760994e88097d223b048e42f561046c602405683524f00b4cd3eec7e67259c47e90203010001 
//<IGNORE><--------------------------------------------- MODULUS --------------------------------------------------------------------------><??><PK> 
// We're interested in the modulus and the public key. 
// PK = Public key, probably 65537 

// First, generate the sha1 of the hash string: 
$sha1 = sha1($hashString,true); 

// Unencode the user's public Key: 
$pkstr = base64_decode($publicKey); 
// Skip the <IGNORE> section: 
$a = 4; 
// Find the very last occurrence of \x02\x03 which seperates the modulus from the PK: 
$d = strrpos($pkstr,"\x02\x03"); 
// If something went wrong, give up: 
if ($a == false || $d == false) return false; 
// Extract the modulus and public key: 
$modulus = substr($pkstr,$a,($d-$a)); 
$pk = substr($pkstr,$d+2); 

// 1) Take the $signature from the user 
// 2) Decode it from base64 to binary 
// 3) Convert the binary $pk and $modulus into (very large!) integers (stored in strings in PHP) 
// 4) Run rsa_verify, from http://www.edsko.net/misc/rsa.php 
$unencoded_signature = rsa_verify(base64_decode($signature), binary_to_number($pk), binary_to_number($modulus), "512"); 

//Finally, does the $sha1 we calculated match the $unencoded_signature (less any padding bytes on the end)? 
return ($sha1 == substr($unencoded_signature,-20)); // SHA1 is only 20 bytes, whilst signature is longer than this. 

उद्देश्य-सी है कि यह सार्वजनिक कुंजी उत्पन्न करता है:

NSData * data = [[SecKeyWrapper sharedWrapper] getPublicKeyBits]; 
[req addValue:[data base64Encoding] forHTTPHeaderField: @"X-Public-Key"]; 
data = [[SecKeyWrapper sharedWrapper] getSignatureBytes:[signatureData dataUsingEncoding:NSUTF8StringEncoding]]; 
[req addValue:[data base64Encoding] forHTTPHeaderField: @"X-Signature"]; 

एप्पल के उदाहरण परियोजना CryptoExercise से SecKeyWrapper का उपयोग करना (आप फ़ाइल यहाँ देख सकते हैं: https://developer.apple.com/iphone/library/samplecode/CryptoExercise/listing15.html)

मुझे आशा है कि इससे मदद मिलती है?

+0

के रूप में जॉन अनुदान का सुझाव दिया, मैं सार्वजनिक कुंजी बिट्स खुद को निरीक्षण करेंगे लेकिन तथ्य यह है कि iPhone एक X509 प्रमाणपत्र एप्लिकेशन (फोन पर ही उत्पन्न नहीं) के साथ बंडल पढ़ रही है और मैं यह अविश्वसनीय फोन सार्वजनिक पढ़ा होगा कि लगता है अलग-अलग कुंजी। मैं इसे बाइट्स की जांच करके व्यवस्थित कर दूंगा, लेकिन अगर ऐसा है तो मैं बहुत आश्चर्यचकित होने जा रहा हूं। – bbrown

संबंधित मुद्दे