2

Java PBEWithMD5AndDES実装アルゴリズムを次に示します。

外部ライブラリを使用せずに、iOS プラットフォーム用のObjective-C で正確に同等のものを探しています。承認されたソリューションは、iOS SDK に含まれるライブラリにのみ依存する必要があります。

以下の Java は、 「bar」をパスフレーズ「foo」「0WUc+boDvbU=」として暗号化します。

new DesEncrypter("foo").encrypt("bar") == "0WUc+boDvbU="

しかし、obj-c コードはパスフレーズ「foo」「VRWOhmfj2g8=」として「 bar」を暗号化します。

 NSString* encrypted = [ self encrypt:@"bar"]; == "VRWOhmfj2g8="

私が探しているのは、Java と同じように「bar」を「0WUc+boDvbU=」として暗号化する obj-c 暗号化メソッドです。

Java コード:

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;


public class DesEncrypter {
    private Cipher ecipher;

    private Cipher dcipher;

    private byte[] salt = {(byte) 0x10, (byte) 0x1B, (byte) 0x12, (byte) 0x21, (byte) 0xba, (byte) 0x5e,
            (byte) 0x99, (byte) 0x12};

    public DesEncrypter(String passphrase) throws Exception {
        int iterationCount = 2;
        KeySpec keySpec = new PBEKeySpec(passphrase.toCharArray(), salt, iterationCount);
        SecretKey key = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(keySpec);
        ecipher = Cipher.getInstance(key.getAlgorithm());
        dcipher = Cipher.getInstance(key.getAlgorithm());

        AlgorithmParameterSpec paramSpec = new PBEParameterSpec(salt, iterationCount);

        ecipher.init(Cipher.ENCRYPT_MODE, key, paramSpec);
        dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
    }

    public String encrypt(String str) throws Exception {
        return new BASE64Encoder().encode(ecipher.doFinal(str.getBytes())).trim();
    }

    public String decrypt(String str) throws Exception {
        return new String(dcipher.doFinal(new BASE64Decoder().decodeBuffer(str))).trim();
    }
}

Obj-c コード

- (NSString*) encrypt:(NSString*)encryptValue {
    const void *vplainText;
    size_t plainTextBufferSize = [encryptValue length];
    vplainText = (const void *) [encryptValue UTF8String];
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    bufferPtrSize = (plainTextBufferSize + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    unsigned char salt [] =  {0x10,0x1B,0x12,0x21,0xba,0x5e,0x99,0x12};
    NSString *key = @"foo";
    const void *vkey = (const void *) [key UTF8String];
    ccStatus = CCCrypt(kCCEncrypt,kCCAlgorithmDES,kCCOptionPKCS7Padding,vkey,kCCKeySizeDES,salt,vplainText,
                       plainTextBufferSize,(void *)bufferPtr,bufferPtrSize,&movedBytes);
    NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
    NSString *result = [myData base64Encoding];
    return result;
}
4

4 に答える 4

2

このアルゴリズムで要求されるキーを準備するのを忘れました。これを行うと、出力は Java 版と同じになります。

- (NSString *)encrypt:(NSString *)encryptValue {
    // first of all we need to prepare key with md5
    // setup md5 context with salt and key
    NSString *key = @"foo";
    unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
    memset(md5Buffer, 0, CC_MD5_DIGEST_LENGTH);
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
    CC_MD5_CTX md5Ctx;
    CC_MD5_Init(&md5Ctx);
    CC_MD5_Update(&md5Ctx, [keyData bytes], [keyData length]);
    unsigned char salt[] =  {0x10,0x1B,0x12,0x21,0xba,0x5e,0x99,0x12};
    CC_MD5_Update(&md5Ctx, salt, 8);
    CC_MD5_Final(md5Buffer, &md5Ctx);

    // do md5 hashing
    CC_MD5(md5Buffer, CC_MD5_DIGEST_LENGTH, md5Buffer);

    // our key is ready, let's prepare other buffers and moved bytes length
    NSData *encryptData = [encryptValue dataUsingEncoding:NSUTF8StringEncoding];
    size_t resultBufferSize = [encryptData length] + kCCBlockSizeDES;
    unsigned char resultBuffer[resultBufferSize];
    size_t moved = 0;

    // DES-CBC requires an explicit Initialization Vector (IV)
    // IV - second half of md5 key
    unsigned char IV[kCCBlockSizeDES];
    memcpy(IV, md5Buffer + CC_MD5_DIGEST_LENGTH / 2, sizeof(IV));

    CCCryptorStatus cryptorStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
                                        kCCOptionPKCS7Padding, md5Buffer,
                                        CC_MD5_DIGEST_LENGTH/2, IV,
                                        [encryptData bytes], [encryptData length],
                                        resultBuffer, resultBufferSize, &moved);

    if (cryptorStatus == kCCSuccess) {
        return [[NSData dataWithBytes:resultBuffer length:moved] base64EncodedStringWithOptions:0];
    } else {
        return nil;
    }
}

出力: 0WUc+boDvbU=

于 2013-11-19T21:49:35.877 に答える
1

可能性の 1 つは、String.getBytes() がプラットフォームのデフォルトの文字セットで byte[] を返すことです。String.getBytes("UTF-8") を使用することをお勧めします

Java コードの反復回数は 2 に設定されていますが、目的の C バージョンではそれが見られません。

于 2013-11-17T21:52:28.310 に答える
0

単なる提案ですが、iOS でさまざまなパディング オプションを試しましたか? 現在使用しているパディングは kCCOptionPKCS7Padding のようです。これは単純な変更であり、追加情報が提供される可能性があります...

于 2013-11-19T15:03:52.013 に答える