【问题标题】:How to implement laravel function Crypt::encrypt() in Objective C?如何在 Objective C 中实现 laravel 函数 Crypt::encrypt()?
【发布时间】:2017-05-23 09:49:08
【问题描述】:

我需要从 laravelObjective C iOS 实现 Crypt::ecrypt('123456');。所以首先我将laravel这样的加密方法扩展到纯php:

public function enc($text,$key)
    {
        $key = (string)base64_decode($key);
        $iv = random_bytes(16);
        $value = \openssl_encrypt(serialize($text), 'AES-256-CBC', $key, 0, $iv);  
        $bIv = base64_encode($iv);
        $mac = hash_hmac('sha256', $bIv.$value, $key); 
        $c_arr = ['iv'=>$bIv,'value'=>$value,'mac'=>$mac];
        $json = json_encode($c_arr);
        $crypted = base64_encode($json);

        return $crypted; 
    }

https://github.com/reza-khalafi/LaravelCrypt/blob/master/laravelEncrypt.php

然后把这段代码的每一行一步步转换成objective c。观看我的目标 c 代码:

#import <CommonCrypto/CommonHMAC.h>
#import <CommonCrypto/CommonCryptor.h>


// First convert Base64 strings to data
NSString *stringIn = @"123456";
NSString *ser = [NSString stringWithFormat:@"s:%lu:\"%@\";",(unsigned long)stringIn.length,stringIn];
NSData *dataIn     = [ser dataUsingEncoding:NSUTF8StringEncoding];

//Make iv
uint8_t randomBytes[16];
NSMutableString *ivStr;
int result = SecRandomCopyBytes(kSecRandomDefault, 16, randomBytes);
if(result == 0) {
    ivStr = [[NSMutableString alloc] initWithCapacity:16];
    for(NSInteger index = 0; index < 8; index++)
    {
        [ivStr appendFormat: @"%02x", randomBytes[index]];
    }
    NSLog(@"uuidStringReplacement is %@", ivStr);
} else {
    NSLog(@"SecRandomCopyBytes failed for some reason");
}
NSData *iv         = [[NSData alloc] initWithBase64EncodedString:ivStr options:0];

//Iv base 64
NSString *bIV = [[ivStr dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];

//Key
NSString *key = @"9OsNt7h7vjhvOwzXLfdQQYcHxYTua1Fk";
NSData *decodedKeyData = [[NSData alloc] initWithBase64EncodedString:key options:0];
NSString *keyStr = [[NSString alloc] initWithData:decodedKeyData encoding:NSISOLatin1StringEncoding];

//Encryption
size_t         encryptBytes = 0;
NSMutableData *encrypted  = [NSMutableData dataWithLength:ser.length + kCCBlockSizeAES128];
CCCrypt(
        kCCEncrypt,
        kCCAlgorithmAES128,
        kCCOptionPKCS7Padding, //CBC is the default mode
        decodedKeyData.bytes,
        kCCKeySizeAES128,
        iv.bytes,
        dataIn.bytes,
        dataIn.length,
        encrypted.mutableBytes,
        encrypted.length,
        &encryptBytes
        );

encrypted.length = encryptBytes;
NSLog(@"encrypted hex:    %@", encrypted);
NSString *encStr = [encrypted base64EncodedStringWithOptions:0];
NSLog(@"encrypted Base64: %@", encStr);


//Combine two string
NSString *mixStr = [NSString stringWithFormat:@"%@%@",bIV,encStr];

//cHMAC
const char *cKey  = [keyStr cStringUsingEncoding:NSISOLatin1StringEncoding];
const char *cData = [mixStr cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSMutableString *mac = [NSMutableString string];
for (int i=0; i<sizeof cHMAC; i++){
    [mac appendFormat:@"%02hhx", cHMAC[i]];
}

//Make dictionary
NSDictionary *dic = @{@"iv":bIV,@"value":encStr,@"mac":mac};

//Json
NSError  * err;
NSData   * jsonData = [NSJSONSerialization dataWithJSONObject:dic options:0 error:&err];
NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

//Result
NSString *lastEnc = [[myString dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];

NSLog(@"%@ %lu",lastEnc,(unsigned long)lastEnc.length);

代码结果包含 192 或 188 个字符的字符串,这没关系。但是在目的地使用此代码时,响应显示错误:

Could not decrypt the data.  

我更改了一些代码,并测试了这些方法。所有功能都是正确的,但我认为 CCCryptopenssl_encrypt 不匹配。因为当我从 php 获得 openssl_encrypt 的结果并设置它而不是 encStr 时,总结果可以正常工作。

谢谢

【问题讨论】:

标签: php ios objective-c encryption aes


【解决方案1】:
 $value = \openssl_encrypt(serialize($text), 'AES-256-CBC', $key, 0, $iv);  

serialize 函数 - 它看起来像是特定于 php 的,并且它在非 ASCII 编码下工作不正确。如果你用 base64_encode 替换它呢?当然你也需要修改解密代码。

【讨论】:

  • 也许我应该设置 NSISOLatin1StringEncoding?
【解决方案2】:

已解决
最后我们对Laravel加密研究了太多时间,决定自己创建。 LaraCrypt 解决了这个问题。试试这个:

pod 'LaraCrypt'

Laravel Encryption with Swift language

取得成功。

【讨论】:

    猜你喜欢
    • 2017-05-10
    • 1970-01-01
    • 2015-11-08
    • 1970-01-01
    • 2016-09-27
    • 2011-04-14
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    相关资源
    最近更新 更多