4

両方の (Android と IPhone) プラットフォームで AES アルゴリズムを使用して暗号化されたテキストを生成しようとしましたが、問題は、同じ暗号化復号化ライブラリ (AES-128) と同じ固定変数 ( Key 、 IV 、モード) を使用することです。それらに対して2つの異なる結果が得られます。

助けていただければ幸いです。:(

以下のコードは、使用されている暗号化と復号化の方法を示しています。

Android のコード バージョン:

  • キー = “123456789abcdefg” ;
    • IV = "1111111111111111" ;
    • 平文 = “HelloThere”;
    • モード = "AES/CBC/NoPadding" ;

コード :

  public class Crypto {
public static String encrypt(String seed, String cleartext) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] result = encrypt(rawKey, cleartext.getBytes());
        return toHex(result);
}



public static String decrypt(String seed, String encrypted) throws Exception {
        byte[] rawKey = getRawKey(seed.getBytes());
        byte[] enc = toByte(encrypted);
        byte[] result = decrypt(rawKey, enc);
        return new String(result);
}


private static byte[] getRawKey(byte[] seed) throws Exception {
        KeyGenerator kgen = KeyGenerator.getInstance(“CBC”);
        SecureRandom sr = SecureRandom.getInstance(“SHA1PRNG”);
        sr.setSeed(seed);
    kgen.init(128, sr); // 192 and 256 bits may not be available
    SecretKey skey = kgen.generateKey();
    byte[] raw = skey.getEncoded();
    return raw;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, “AES”);
        Cipher cipher = Cipher.getInstance(“AES”);
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(clear);
        return encrypted;
}
private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
    SecretKeySpec skeySpec = new SecretKeySpec(raw, “AES”);
        Cipher cipher = Cipher.getInstance(“AES”);
    cipher.init(Cipher.DECRYPT_MODE, skeySpec);
    byte[] decrypted = cipher.doFinal(encrypted);
        return decrypted;
}
public static String toHex(String txt) {
        return toHex(txt.getBytes());
}
public static String fromHex(String hex) {
        return new String(toByte(hex));
}
public static byte[] toByte(String hexString) {
        int len = hexString.length()/2;
        byte[] result = new byte[len];
        for (int i = 0; i < len; i++)
                result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue();
        return result;
}
public static String toHex(byte[] buf) {
        if (buf == null)
                return “”;
        StringBuffer result = new StringBuffer(2*buf.length);
        for (int i = 0; i < buf.length; i++) {
                appendHex(result, buf[i]);
        }
        return result.toString();
}
private final static String HEX = “0123456789ABCDEF”;
private static void appendHex(StringBuffer sb, byte b) {
        sb.append(HEX.charAt((b»4)&0x0f)).append(HEX.charAt(b&0x0f));
}

}

IPhone のコード バージョン:

- (NSData *) transform:(CCOperation) encryptOrDecrypt data:(NSData *) inputData {

NSData* secretKey = [Cipher md5:cipherKey];

CCCryptorRef cryptor = NULL;
CCCryptorStatus status = kCCSuccess;

uint8_t iv[kCCBlockSizeAES128];
memset((void *) iv, 0x0, (size_t) sizeof(iv));

status = CCCryptorCreate(encryptOrDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                         [secretKey bytes], kCCKeySizeAES128, iv, &cryptor);

if (status != kCCSuccess) {
    return nil;
}

size_t bufsize = CCCryptorGetOutputLength(cryptor, (size_t)[inputData length], true);

void * buf = malloc(bufsize * sizeof(uint8_t));
memset(buf, 0x0, bufsize);

size_t bufused = 0;
size_t bytesTotal = 0;

status = CCCryptorUpdate(cryptor, [inputData bytes], (size_t)[inputData length],
                         buf, bufsize, &bufused);

if (status != kCCSuccess) {
    free(buf);
    CCCryptorRelease(cryptor);
    return nil;
}

bytesTotal += bufused;

status = CCCryptorFinal(cryptor, buf + bufused, bufsize - bufused, &bufused);

if (status != kCCSuccess) {
    free(buf);
    CCCryptorRelease(cryptor);
    return nil;
}

bytesTotal += bufused;

CCCryptorRelease(cryptor);

return [NSData dataWithBytesNoCopy:buf length:bytesTotal];

}

 + (NSData *) md5:(NSString *) stringToHash {

const char *src = [stringToHash UTF8String];

unsigned char result[CC_MD5_DIGEST_LENGTH];

CC_MD5(src, strlen(src), result);

return [NSData dataWithBytes:result length:CC_MD5_DIGEST_LENGTH];

}

私の参照のいくつか:

4

3 に答える 3

4

最初に確認することは、使用しているバイトです。IV、キー、平文を文字としてリストします。これらの文字は、何らかのエンコーディングを使用してバイトに変換されます。文字ではなく、バイトがどのように見えるかを確認してください。両方のマシンですべてをバイトごとにリストして比較する必要があります。または、各マシンで使用する変換を正確に指定します。マシンのデフォルトは異なる可能性があります。

入力バイトが同じであることがわかったら、他の問題を探すことができます。

マイナーな点として、PKCS#7 などのパディングを使用する方が一般的に優れています。そうすれば、メッセージをサイファーのブロック サイズに合わせる必要がなくなります。

于 2012-10-31T14:20:38.900 に答える
3

ああ、あなたは .getBytes("UTF-8"); を使うのを忘れていました。...

かなり重要。

編集:

この回答の品質を改善する必要があることはわかっていますが、ここで言ったこと + 以下でロッサムが言ったことは、これを正しくするための秘訣です。

暗号化/復号化のコンプライアンスについてです。プラットフォーム間で作業している場合は、バイナリのコンプライアンスも必要です。

したがって、生データをダンプして不一致がないかどうかを調べて、目が血を流し、その違いを生む小さな癖を見つけてパッチを当てることに成功します。

手始めに、.getBytes("UTF-8") は、Java/Android 環境全体で一貫した文字列を取得します (ドキュメントを読まない限り、getBytes() は期待どおりに機能しないため)。

于 2012-10-31T14:45:39.763 に答える
0

コードにはさまざまな問題がありますが、Android で暗号化ごとに異なる暗号文を取得する原因は、IV を指定しておらず、ランダムな IV が生成されているためです。また、「パディングなし」と言いますが、iOS コードはパディングを行っており、明示的に指定していないため、Android もおそらくデフォルトでパディングされています。最後に、ブロック サイズの倍数ではないものを暗号化する場合は、パディングが必要です (サンプルのプレーン テキストのように)。getBytes()Android ではデフォルトで UTF-8 に設定されているため、問題は最小限ですが、明示的にしてください。

于 2012-11-01T03:36:48.257 に答える