2012-10-31 2 views
3

AES 알고리즘을 사용하여 암호화 된 텍스트를 생성하려고 시도했지만 (Android 및 IPhone) 플랫폼 모두에서 동일한 암호화 해독 라이브러리 (AES-128)를 사용하고 동일한 고정 변수 (키, IV, 모드)하지만 두 가지 결과가 나타납니다.iPhone 및 Android 용 암호화 방법

감사합니다. :(

아래의 코드는 사용되는 암호화 및 암호 해독 방법, 안드로이드에 대한

코드 버전 제공 :;

  • IV = "1111111111111111"

    • 키 = "123456789abcdefg을";
    • 일반 텍스트 = "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 = “ABCDEF”; 
private static void appendHex(StringBuffer sb, byte b) { 
     sb.append(HEX.charAt((b»4)&0x0f)).append(HEX.charAt(b&0x0f)); 
} 

}

코드 버전 :

- (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]; 

}

일부 :

+0

문자열의 getBytes() 메소드가 매번 동일한 문자열을 반환하지 않을 것을 염두에 두십시오 –

+0

이것을 통해 Java 및 Objective-C 버전의 출력을 암호 해독 해 보았습니까? http://www.everpassword.com/aes-encryptor –

+0

당신은 기본 plaintext.equals (decrypt (encrypt (plaintext))) 테스트를 시도 했습니까? 그들은 두 가지 방법 모두에 대해 사실로 돌아갈 수 있습니까? – Shark

답변

4

우선 확인하기 위해 사용중인 바이트입니다. IV, 키 및 일반 텍스트를 문자로 나열합니다. 이러한 문자는 일종의 인코딩을 사용하여 바이트로 변환됩니다. 문자가 아닌 바이트이 무엇인지 확인하십시오. 두 시스템 모두에서 모든 것을 바이트 단위로 나열하고 비교해야합니다. 또는 각 컴퓨터에서 사용할 변환을 정확히 지정하십시오. 기계 기본값은 다를 수 있습니다.

입력 바이트가 동일하다는 것을 알게되면 다른 문제를 찾을 수 있습니다.

일반적으로 PKCS # 7과 같은 패딩을 사용하는 것이 좋습니다. 그렇게하면 메시지를 사이퍼의 블록 크기에 맞출 필요가 없습니다.

+0

고마워요,하지만 바이트를 테스트했습니다.)하지만 결과는 같지 않습니다. 어떤 제안? 패딩에 대해 필자는 PKCS 패딩과 패딩 모드를 시도하지 않았지만 PHP 서버는 패딩을 사용하지 않기 때문에 패딩 모드가 제한적이라는 생각이 듭니다. –

3

오, 당신은 잊어 버렸습니다. .getBytes ("UTF-8"); ...

매우 중요합니다.

편집 :

나는 내가이 답변의 품질하지만 내가 여기 말했다 + 어떤 로섬 아래 말했다이 권리를 얻는 데 트릭을 개선해야한다 알고있다.

이것은 암호화/암호 해독 준수에 관한 것입니다. 플랫폼을 넘어서 일할 때 바이너리 호환성을 준수해야합니다.

원시 데이터를 덤프하고 눈이 뚝뚝 끊어 질 때까지 불일치가 있는지 검사하고 그 차이를 만드는 작은 단점을 발견하고 성공적으로 패치합니다.

처음에는 .getBytes ("UTF-8")를 사용하면 Java/Android 환경에서 일관된 문자열을 얻을 수 있습니다 (getBytes()는 문서를 읽지 않는 한 작동 할 수있는 방식으로 작동하지 않기 때문에)

+0

고맙습니다. 이미 두 플랫폼 모두에서 getBytes ("UTF-8")를 시도했지만 다른 결과가 있습니다. –

0

코드에는 여러 가지 문제가 있지만 Android의 각 암호화에서 다른 암호문을받는 이유는 IV를 지정하지 않고 임의의 암호가 생성된다는 것입니다. 또한 '패딩 없음'이라고 말하지만 iOS 코드가 패딩을 수행하고 있으며 Android를 명시 적으로 지정하지 않았기 때문에 Android가 기본적으로 기본 설정 일 가능성이 큽니다. 마지막으로 블록 크기의 배수가 아닌 것을 암호화하는 경우 (예 : 일반 텍스트 그대로) 패딩이 필요합니다. getBytes()은 Android에서 UTF-8로 기본 설정되어 있으므로 문제가 될 수는 없지만 명시 적으로 설정하십시오.

+0

제공된 링크에서 실수를해서 죄송합니다. 동일한 IV (하드 코딩 됨)와 iOS 코드의 패딩 없음을 모두 시도했지만 두 플랫폼 모두 다른 결과를 얻었습니다. getBytes ("UTF-8")도 사용했지만 결과는 여전히 다릅니다. 패딩 유형에 대해서는 미안하지만 PHP 서버는 패딩 없음 모드를 사용하므로이 모드에 엄격합니다. 도움을 청하십시오. –

+0

'패딩 금지'는 사용자가 직접 패딩해야한다는 것을 의미합니다. 그렇지 않으면 오류가 발생합니다. 코드를 업데이트하여 IV 사용법을 보여줍니다. –

관련 문제