zoukankan      html  css  js  c++  java
  • iOS Objective-C 與 PHP DES 加解密演算法實作


    原文:http://blog.toright.com/archives/2657

    在使用 php-mcrypt 函式庫進行 DES 加解密時,常常會碰到在其他平台無法正確解密資料>,是因為 PHP Mcrypt Library 沒有提供將明文訊息轉換為標準 PKCS#7 的格式 (定義在 RFC 5652) 所造成。以下程式碼說明使用 PHP mcrypt_encrypt function 依據 PKCS#7 規範

    對字串進行 DES 加密,並且使用 Base64 編碼後輸出後再使用 DES 解密後的結果 (包含 iOS 的 DES 解密實作)。遵循標準的 PKCS#7 規範實作,密文在其他的程式語言中才能正確>地進行解密。以下為 PHP DES 加解密的程式碼,後面會介紹 Object-C 的加解密實作。

    <?php
    /**
     * PHP DES 加密程式
     *
     * @param $key 密鑰(八個字元內)
     * @param $encrypt 要加密的明文
     * @return string 密文
     */
    function encrypt ($key, $encrypt)
    {
        // 根據 PKCS#7 RFC 5652 Cryptographic Message Syntax (CMS) 修正 Message 加入 Padding
        $block = mcrypt_get_block_size(MCRYPT_DES, MCRYPT_MODE_ECB);
        $pad = $block - (strlen($encrypt) % $block);
        $encrypt .= str_repeat(chr($pad), $pad);
    
        // 不需要設定 IV 進行加密
        $passcrypt = mcrypt_encrypt(MCRYPT_DES, $key, $encrypt, MCRYPT_MODE_ECB);
        return base64_encode($passcrypt);
    }
    
    /**
     * PHP DES 解密程式
     *
     * @param $key 密鑰(八個字元內)
     * @param $decrypt 要解密的密文
     * @return string 明文
     */
    function decrypt ($key, $decrypt)
    {
        // 不需要設定 IV
        $str = mcrypt_decrypt(MCRYPT_DES, $key, base64_decode($decrypt), MCRYPT_MODE_ECB);
    
        // 根據 PKCS#7 RFC 5652 Cryptographic Message Syntax (CMS) 修正 Message 移除 Padding
        $pad = ord($str[strlen($str) - 1]);
        return substr($str, 0, strlen($str) - $pad);
    }
    
    $key = 'uuid';
    $plain = '0123ABCD!@#$中文';
    $encrypt = encrypt($key, $plain);
    $decrypt = decrypt($key, $encrypt);
    
    echo 'plain = '.$plain."
    ";
    echo 'encrypt = '.$encrypt."
    ";
    echo 'decrypt = '.$decrypt."
    ";
    ?>

    PHP 執行結果如下:

    plain = 0123ABCD!@#$中文
    encrypt = fDDkBvvC7KJAcmU9IB6aptxMZ35cn4ZX
    decrypt = 0123ABCD!@#$中文

    那在 iOS 中該如何進行解密呢?我們可以透過 iOS 內建的 CommonCryptor 函式庫進行 DES 加解密,使用時記得加入以下程式碼來引入需要的 Header。

    #include <CommonCrypto/CommonCryptor.h>

    在 iOS 對於 Base64 編碼 (解碼) 的實作,我們可以引用 GTM Library GTMBase64 Class 來進行,這時需要 GTMBase64.h, GTMBase64.m, GTMDefines.h 這三支檔案,程式可以在 GTM Source Code 下載。GTM 全名為 Google Toolbox for MAC,其中實作了許多好用的函式
    庫,並且使用 Apache License 2.0 作為授權。經過比較發現 GTMBase64 在實作上確實比>較完整,因此我們採用 GTMBase64 作為編碼函式。Objective-C 實作 DES 解密,程式碼如
    下:

    -(NSString*) decryptUseDES:(NSString*)cipherText key:(NSString*)key {
        // 利用 GTMBase64 解碼 Base64 字串
        NSData* cipherData = [GTMBase64 decodeString:cipherText];
        unsigned char buffer[1024];
        memset(buffer, 0, sizeof(char));
        size_t numBytesDecrypted = 0;
    
        // IV 偏移量不需使用
        CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                              kCCAlgorithmDES,
                                              kCCOptionPKCS7Padding | kCCOptionECBMode,
                                              [key UTF8String],
                                              kCCKeySizeDES,
                                              nil,
                                              [cipherData bytes],
                                              [cipherData length],
                                              buffer,
                                              1024,
                                              &numBytesDecrypted);
        NSString* plainText = nil;
        if (cryptStatus == kCCSuccess) {
            NSData* data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted];
            plainText = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
        }
        return plainText;
    }

    接下來我們將剛剛 PHP 輸出的 Base64 密文進行解密,參考以下程式碼:

    // 設定 key
    NSString* key = @"skey";
    NSString* encrypt = @"fDDkBvvC7KJAcmU9IB6aptxMZ35cn4ZX";
    NSString* decrypt = [self decryptUseDES:encrypt key:key];
    
    // 輸出
    NSLog(@"encrypt = %@", encrypt);
    NSLog(@"decrypt = %@", decrypt);

    執行結果輸出到 console,輸出資料如下:

    2012-06-26 16:50:28.092 test[15666:13403] encrypt = fDDkBvvC7KJAcmU9IB6aptxMZ35cn4ZX
    2012-06-26 16:50:28.093 test[15666:13403] decrypt = 0123ABCD!@#$中文

    最後補充一下網友(waxdoll)所提供的 Object-C DES 加密程式,程式碼如下:

    -(NSString *) encryptUseDES:(NSString *)clearText key:(NSString *)key
    {
        NSData *data = [clearText dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
        unsigned char buffer[1024];
        memset(buffer, 0, sizeof(char));
        size_t numBytesEncrypted = 0;
    
        CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                              kCCAlgorithmDES,
                                              kCCOptionPKCS7Padding | kCCOptionECBMode,
                                              [key UTF8String],
                                              kCCKeySizeDES,
                                              nil,
                                              [data bytes],
                                              [data length],
                                              buffer,
                                              1024,
                                              &numBytesEncrypted);
    
        NSString* plainText = nil;
        if (cryptStatus == kCCSuccess) {
            NSData *dataTemp = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted];
            plainText = [GTMBase64 stringByEncodingData:dataTemp];
        }else{
            NSLog(@"DES加密失败");
        }
        return plainText;
    }

  • 相关阅读:
    Server SQL Modes
    Java 8 New Features
    Spring Boot 企业级应用开发实战 刘伟东-2018年3月第一版
    一步一步学Spring Boot 2 微服务项目实战
    Springboot揭秘-快速构建微服务体系-王福强-2016年5月第一次印刷
    深圳宝安图书馆官网错误 HTTP Status 500
    Springboot
    linux 操作 mysql 指定端口登录 以及启动 停止
    PHP 基础
    Magento 总结
  • 原文地址:https://www.cnblogs.com/iapp/p/3631674.html
Copyright © 2011-2022 走看看