আইফোনে একটি এনএসএসস্ট্রিংয়ের জন্য এইএস এনক্রিপশন


124

এনক্রিপ্ট করা ডেটা দিয়ে অন্য স্ট্রিংটি ফিরিয়ে কোনও স্ট্রিং এনক্রিপ্ট করতে সক্ষম হতে আমাকে সঠিক দিক নির্দেশ করতে পারে? (আমি AES256 এনক্রিপশন দিয়ে চেষ্টা করেছি।) আমি এমন একটি পদ্ধতি লিখতে চাই যা দুটি এনএসএস ট্রান্সিং লাগে, একটি হ'ল এনক্রিপ্ট করার বার্তা এবং অন্যটি এটি দিয়ে এনক্রিপ্ট করার জন্য 'পাসকোড' - আমার সন্দেহ হয় যে আমি উত্পন্ন করতে হবে পাসকোড সহ এনক্রিপশন কীটি এমনভাবে যা যদি এনক্রিপ্ট করা ডেটা দিয়ে পাসকোড সরবরাহ করা হয় তবে বিপরীত হতে পারে। এরপরে পদ্ধতিটি এনক্রিপ্ট হওয়া ডেটা থেকে তৈরি একটি এনএসএসস্ট্রিং ফিরিয়ে আনতে হবে।

আমি এই পোস্টে প্রথম মন্তব্যে বিস্তারিত কৌশলটি চেষ্টা করেছি , তবে এখনও পর্যন্ত আমার ভাগ্য হয়নি। অ্যাপলের ক্রিপ্টো এক্সারসাইজে অবশ্যই কিছু আছে তবে আমি তা বুঝতে পারি না ... আমি সিসিক্রিপ্টের অনেকগুলি রেফারেন্স দেখেছি , তবে এটি প্রতিটি ক্ষেত্রেই এটি ব্যর্থ হয়েছে।

আমাকে একটি এনক্রিপ্ট করা স্ট্রিংটি ডিক্রিপ্ট করতে সক্ষম হতে হবে তবে আমি আশা করি এটি কেসিসিএনক্রিপ্ট / কেসিসিডিক্রিপ্টের মতো সহজ।


1
দয়া করে নোট করুন যে আমি রব নেপিয়ারের উত্তরে একটি উত্তম মূল্য দিয়েছি যিনি উত্তরের সুরক্ষিত সংস্করণ সরবরাহ করেছেন ।
মার্টেন বোদেউয়েস

উত্তর:


126

যেহেতু আপনি কোনও কোড পোস্ট করেন নি, তাই ঠিক কোন সমস্যাগুলির মুখোমুখি হচ্ছেন তা জানা শক্ত। তবে, আপনি যে ব্লগের লিঙ্কটি লিঙ্ক করেছেন সেটি বেশ শালীনভাবে কাজ করবে বলে মনে হচ্ছে ... প্রতিটি কলটিতে অতিরিক্ত কমা বাদে CCCrypt()যা সংকলনের ত্রুটিগুলির কারণ হয়েছিল।

পরবর্তী পোস্টে পরবর্তী মন্তব্যে এই অভিযোজিত কোডটি অন্তর্ভুক্ত রয়েছে যা আমার পক্ষে কাজ করে এবং কিছুটা সোজা মনে হয়। যদি আপনি এনএসডিটা বিভাগের জন্য তাদের কোড অন্তর্ভুক্ত করেন তবে আপনি এই জাতীয় কিছু লিখতে পারেন: (দ্রষ্টব্য: printf()কলগুলি কেবলমাত্র বিভিন্ন পয়েন্টে ডেটার স্থিতি প্রদর্শনের জন্য - একটি বাস্তব প্রয়োগে, এই জাতীয় মানগুলি মুদ্রণ করার কোনও মানে হবে না) ।)

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSString *key = @"my password";
    NSString *secret = @"text to encrypt";

    NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
    NSData *cipher = [plain AES256EncryptWithKey:key];
    printf("%s\n", [[cipher description] UTF8String]);

    plain = [cipher AES256DecryptWithKey:key];
    printf("%s\n", [[plain description] UTF8String]);
    printf("%s\n", [[[NSString alloc] initWithData:plain encoding:NSUTF8StringEncoding] UTF8String]);

    [pool drain];
    return 0;
}

এই কোডটি দেওয়া হয়েছে এবং এনক্রিপ্ট হওয়া ডেটা সর্বদা একটি এনএসএসআর্টিং-এ সুন্দরভাবে অনুবাদ করে না, এমন দুটি পদ্ধতি যা আপনার প্রয়োজনীয় কার্যকারিতা আবদ্ধ করে তা সামনের দিকে এবং বিপরীতে লিখতে আরও সুবিধাজনক হতে পারে ...

- (NSData*) encryptString:(NSString*)plaintext withKey:(NSString*)key {
    return [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
}

- (NSString*) decryptData:(NSData*)ciphertext withKey:(NSString*)key {
    return [[[NSString alloc] initWithData:[ciphertext AES256DecryptWithKey:key]
                                  encoding:NSUTF8StringEncoding] autorelease];
}

এটি স্পষ্টভাবে স্নো চিতাবাঘের জন্য কাজ করে, এবং @ বোজ জানিয়েছে যে কমনক্রিপ্টো আইফোনের কোর ওএসের অংশ। 10.4 এবং 10.5 উভয়ই আছে/usr/include/CommonCrypto , যদিও 10.5 এর ম্যান পেজ রয়েছে CCCryptor.3ccএবং 10.4 নেই, তাই ওয়াইএমএমভি।


সম্পাদনা: নিরাপদ, ক্ষতিহীন রূপান্তরগুলি ব্যবহার করে স্ট্রিং (যদি ইচ্ছা হয়) হিসাবে এনক্রিপ্ট হওয়া ডেটা বাইট উপস্থাপনের জন্য বেস 64 এনকোডিং ব্যবহার করার বিষয়ে এই ফলোআপ প্রশ্নটি দেখুন ।


1
ধন্যবাদ। কমনক্রিপ্টো আইফোনের মূল ওএসের অংশ, এবং আমি 10.6 চালাচ্ছি।
বোজ

1
আমি -1 করেছি, কারণ রেফারেন্স কোড বিপজ্জনকভাবে নিরাপত্তাহীন। পরিবর্তে রব নেপিয়ারের উত্তরটি দেখুন। তার ব্লগ এন্ট্রি " রবনেপিয়ের.এন.এইএস- কম্মক্রিপ্টো এই তথ্যটি কেন অনিরাপদ তা সঠিকভাবে জানায়
এরিক এঙ্গহিম

1
এই সমাধানটি আমার ক্ষেত্রে কার্যকর হয় না। আমার একটি স্ট্রিং রয়েছে যা আমি ডিকোড করতে চাই: U2FsdGVkX1 + MEhsbofUNj58m + 8tu9ifAKRiY / Zf8YIw = এবং আমার কী আছে: 3841b8485cd155d932a2d601b8cee2ec। আপনার সমাধানটি দিয়ে আমি স্ট্রিংটি ডিক্রিপ্ট করতে পারছি না। ধন্যবাদ
জর্জ

এই সমাধানটি XCode7 সহ এল ক্যাপিটনে একটি কোকো অ্যাপ্লিকেশনটিতে কাজ করে না। এআরসি নিষিদ্ধ autorelease
ভোলোমাইক

@ কুইনটায়লর আমি এই উত্তরটি সম্পাদনা করতে পারি, তবে আপনি যথাযথ দেখায় আপনাকে এটি পরিবর্তন করার সুযোগ দিতে চেয়েছিলেন। আমি আপনার কোডটি এখানে মেরামত করেছি । এছাড়াও, আপনি উল্লেখ করতে চাইতে পারেন যে সেই অভিযোজিত কোড ব্যতীত , এটি সংকলন করবে না। সুতরাং, আমি এটি XCode7 সহ এল ক্যাপিটনে একটি কোকো অ্যাপ্লিকেশনটিতে কাজ করতে পেরেছি। এখন আমি যা করার চেষ্টা করছি তা কীভাবে এই ডাটাটি বেস 64 / এনকোড / বেস 64 ডাকেড করতে হবে যাতে কাঁচা ডেটা ফেরানোর পরিবর্তে ট্রানজিটে কোনও ঝামেলা ছাড়াই এটি প্রেরণযোগ্য।
ভলমাইক

46

আমি এনএসডিটা এবং এনএসএসটিংয়ের জন্য বিভাগগুলির সংকলন একসাথে রেখেছি যা জেফ লামারচের ব্লগে পাওয়া সমাধানগুলি এবং কিছু ইঙ্গিতগুলি ব্যবহার করে স্ট্যাক ওভারফ্লোতে কুইন টেলারের করেছে।

এটিতে এসইএস 256 এনক্রিপশন সরবরাহ করতে এনএসডিটা প্রসারিত করতে বিভাগগুলি ব্যবহার করা হয় এবং বেস স্ট্রিংগুলিতে নিরাপদে BASE64- এনকোড এনক্রিপ্ট করা ডেটাতে NSString এর একটি এক্সটেনশন সরবরাহ করা হয়।

এনক্রিপ্টিং স্ট্রিংয়ের জন্য ব্যবহারটি দেখানোর জন্য এখানে একটি উদাহরণ রয়েছে:

NSString *plainString = @"This string will be encrypted";
NSString *key = @"YourEncryptionKey"; // should be provided by a user

NSLog( @"Original String: %@", plainString );

NSString *encryptedString = [plainString AES256EncryptWithKey:key];
NSLog( @"Encrypted String: %@", encryptedString );

NSLog( @"Decrypted String: %@", [encryptedString AES256DecryptWithKey:key] );

সম্পূর্ণ উত্স কোডটি এখানে পান:

https://gist.github.com/838614

সমস্ত সহায়ক ইঙ্গিত জন্য ধন্যবাদ!

- মাইকেল


এনএসএসটিং * কী = @ "আপনারএন্ট্রিপশনকি"; // কোনও ব্যবহারকারীর দ্বারা সরবরাহ করা উচিত আমরা ব্যবহারকারীর সরবরাহকারীর পরিবর্তে আমরা একটি র‌্যান্ডম সুরক্ষিত 256-বিট কী তৈরি করতে পারি।
প্রণব জয়সওয়াল


35

"প্রদত্ত উত্তরের একটি ক্রিপ্টোগ্রাফিকভাবে সুরক্ষিত রূপের" জন্য আপনার অনুরোধের বিষয়ে @ ওয়ালস্টেড, দয়া করে আরএনক্রিপটর দেখুন । আপনি যা অনুরোধ করছেন ঠিক তা করার জন্য এটি তৈরি করা হয়েছিল (এবং এখানে তালিকাভুক্ত কোড সহ সমস্যার প্রতিক্রিয়াতে নির্মিত হয়েছিল)।

আরএনক্রিপটর পিবিকেডিএফ 2 লবণের সাথে ব্যবহার করে, একটি এলোমেলো চতুর্থ সরবরাহ করে এবং এইচএমএসি সংযুক্ত করে (এটি নিজস্ব লবণের সাথে পিবিকেডিএফ 2 থেকে উত্পন্নও হয়। এটি সিঙ্ক্রোনাস এবং অ্যাসিনক্রোনাস অপারেশন সমর্থন করে।


আকর্ষণীয় কোড, এবং সম্ভবত পয়েন্ট মূল্য। পিবিকেডিএফ 2 এর পুনরাবৃত্তি গণনাটি কী এবং আপনি এইচএমএসি ওভার গণনা করবেন? আমি শুধু এনক্রিপ্ট করা ডেটা অনুমান করি? প্রদত্ত ডকুমেন্টেশনে আমি এটি সহজে খুঁজে পাইনি।
মার্টেন বোদেউয়েস

বিশদটির জন্য "সেরা অনুশীলন সুরক্ষা" দেখুন। আমি আইওএসে 10 কে পুনরাবৃত্তি করার প্রস্তাব দিই (আইফোন 4 এ 80 ডলার)। এবং হ্যাঁ, HMAC- এর চেয়ে এনক্রিপ্ট। V2.0 তে এটি আপডেট রয়েছে তা নিশ্চিত করার জন্য আমি আজ রাতে সম্ভবত "ডেটা ফর্ম্যাট" পৃষ্ঠাটি সন্ধান করব (মূল ডক্সটি আপ টু ডেট রয়েছে, তবে আমি ডেটা ফর্ম্যাট পৃষ্ঠাটি সংশোধন করেছি কিনা তা মনে করতে পারছি না)।
রব নেপিয়ার

আহ, হ্যাঁ, ডক্সে রাউন্ডের সংখ্যা খুঁজে পেয়েছে এবং কোডটি দেখেছিল। আমি ক্লিনআপ ফাংশন এবং সেখানে পৃথক এইচএমএসি এবং এনক্রিপশন কীগুলি দেখছি। যদি সময় অনুমতি দেয় তবে আমি চেষ্টা করব এবং আগামীকাল আরও গভীর দর্শন করব। তারপরে আমি পয়েন্টগুলি বরাদ্দ করব।
মার্টেন বোদেউয়েস

5
এনএসডিটাতে এনক্রিপ্ট করুন এবং এটিকে স্ট্রিংয়ে রূপান্তর করতে অনেক বেস 64 এনকোডার ব্যবহার করুন। ডাটা-টু-স্ট্রিং এনকোডার ছাড়া স্ট্রিং থেকে স্ট্রিং এ এনক্রিপ্ট করার কোনও উপায় নেই।
রব নেপিয়ার

1
@ জ্যাক আমার আইনজীবীর পরামর্শে (যিনি রফতানি সম্মতি আইনে আমার দক্ষতার অভাবকে অত্যন্ত বর্ণিল শর্তে বর্ণনা করেছেন…), আমি আর রফতানি সম্মতি আইন সম্পর্কে পরামর্শ দেব না। আপনার উকিলের সাথে আপনার আলোচনা করতে হবে।
রব নেপিয়ার

12

আমি তার উত্তর আপডেট করার জন্য @ কুইনটেলারের উপর কিছুটা অপেক্ষা করেছি, কিন্তু যেহেতু তিনি তা করেন নি, উত্তরটি এখানে আরও স্পষ্টভাবে এবং এমনভাবে দেওয়া হয়েছে যাতে এটি এক্সকোড 7 (এবং সম্ভবত আরও বেশি) লোড হবে। আমি এটি একটি কোকো অ্যাপ্লিকেশনে ব্যবহার করেছি, তবে এটি সম্ভবত কোনও আইওএস অ্যাপ্লিকেশন দিয়েও ঠিক কাজ করবে। কোনও এআরসি ত্রুটি নেই।

আপনার AppDelegate.m বা AppDelegate.mm ফাইলে কোনও @ ইমপ্লিমেন্টেশন বিভাগের আগে আটকান।

#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (AES256)

- (NSData *)AES256EncryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES256,
                                     NULL /* initialization vector (optional) */,
                                     [self bytes], dataLength, /* input */
                                     buffer, bufferSize, /* output */
                                     &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

- (NSData *)AES256DecryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES256,
                                     NULL /* initialization vector (optional) */,
                                     [self bytes], dataLength, /* input */
                                     buffer, bufferSize, /* output */
                                     &numBytesDecrypted);

    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

@end

আপনার ইচ্ছা ইমপ্লিমেন্টেশন ক্লাসে এই দুটি ফাংশন আটকান। আমার ক্ষেত্রে, আমি আমার অ্যাপডিলেগেট.মি বা অ্যাপডেলিগেট.এম ফাইলটিতে @ কার্যকরকরণ অ্যাপ্লিকেশন বেছে নিয়েছি।

- (NSString *) encryptString:(NSString*)plaintext withKey:(NSString*)key {
    NSData *data = [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
    return [data base64EncodedStringWithOptions:kNilOptions];
}

- (NSString *) decryptString:(NSString *)ciphertext withKey:(NSString*)key {
    NSData *data = [[NSData alloc] initWithBase64EncodedString:ciphertext options:kNilOptions];
    return [[NSString alloc] initWithData:[data AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
}

দ্রষ্টব্য: 1. প্যাডিং থাকাকালীন ডিক্রিপ্টে আউটপুট আকার ইনপুট আকারের চেয়ে কম হবে (পিকেসিএস # 7)। বাফার সাইজ বাড়ানোর কোনও কারণ নেই, কেবল এনক্রিপ্ট করা ডেটার আকার ব্যবহার করুন। 2. পরিবর্তে একটি বাফার malloc'ing এবং তারপর এর dataWithBytesNoCopyশুধু একটি বরাদ্দ NSMutableDataদিয়ে dataWithLengthএবং ব্যবহার mutableBytesবাইট পয়েন্টার জন্য সম্পত্তি এবং তারপর এটা সেট করে রিসাইজ lengthসম্পত্তি। ৩. সরাসরি কোনও এনক্রিপশনের জন্য স্ট্রিং ব্যবহার করা অত্যন্ত সুরক্ষিত, একটি উত্পন্ন কী ব্যবহার করা উচিত যেমন পিবিকেডিএফ 2 দ্বারা তৈরি।
জাফ

@ জাফ, আপনি কি কোথাও একটি পেস্টবিন / পেস্টি করতে পারেন যাতে আমি পরিবর্তনগুলি দেখতে পারি? বিটিডাব্লু, উপরের কোডে, আমি কুইন টেলরের কাছ থেকে দেখেছি কোডটি কাজ করার জন্য কেবলই খাপ খেয়েছি। আমি এখনও যেতে যেতে এই ব্যবসাটি শিখছি এবং আপনার ইনপুটটি আমার পক্ষে খুব কার্যকর হবে।
ভলমিকে

এই এসও উত্তরটি দেখুন এবং এটিতে সর্বনিম্ন ত্রুটি পরিচালনাও রয়েছে এবং এনক্রিপশন এবং ডিক্রিপশন উভয়ই পরিচালনা করে। ডিক্রিপশনটিতে বাফারকে সীমাবদ্ধ করার প্রয়োজন নেই, যখন খুব সামান্য কিছু করা দরকার হয় তবে এটি অতিরিক্ত সংযোজন না করা কম কোড is NULLs আকাঙ্ক্ষিত সঙ্গে কী (যে সম্পন্ন করা উচিত) ব্যাপ্ত যদি কোন প্রমাণ পেতাম একটি চপল সংস্করণ তৈরি এবং দৈর্ঘ্য সেট করুন: keyData.length = kCCKeySizeAES256;
জাফ

স্ট্রিং থেকে কী তৈরি করতে PBKDF2 ব্যবহার করার জন্য এই উত্তরটি দেখুন ।
জাফ

@ ভলোমাইক যদি আমি এটি ব্যবহার করি তবে আমি কি আইটিউনস-কানেক্টে রফতানি কমপ্লায়েন্স ইনফরমেশন (হ্যাঁ) নির্বাচন করব ?
জ্যাক

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.