문제

iPhone에서 문자열을 암호화하여 암호 해독을 위해 .NET 웹 서비스로 보내야합니다. iPhone과 .NET에서 암호화/해독 할 수 있지만 iPhone의 암호화 된 문자열은 .NET에 의해 해독 될 수 없습니다. 내가 얻는 오류는 "패딩이 유효하지 않아 제거 할 수 없습니다"입니다.

.NET 코드는 다음과 같습니다.http://blog.realcoderscoding.com/index.php/2008/07/dot-net-encryption-simple-aes-wrapper/

iPhone 코드는 샘플 코드를 사용합니다. http://nootech.wordpress.com/2009/01/17/symmetric-encryption-with-the-iphone-sdk/

afaik 내 주요 설정은 동일합니다.

result.BlockSize = 128; // iPhone: kCCBlockSizeAES128
result.KeySize = 128; // kCCBlockSizeAES128
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7; // kCCOptionPKCS7Padding

암호 텍스트를 생성하는 다른 방법을 시도했습니다. 안녕하세요/안녕하세요 :

e0pnmbtg/3ct3w+92cdw1q == .net

yrke5z7p7mnqx9+cbbvnqq == iPhone

및 "OpenSSL ENC -AES -128 -CBC -NOSALT -A -IN Hello.txt -Pass Pass : Hello"Generates : QA+UL+R6ZMR7YHIPMCHSBQ ==

업데이트: 여기에 작업 코드를 게시했습니다.

도움이 되었습니까?

해결책

최소한 다른 초기화 벡터 (IV)를 사용하고 있습니다.

  • .NET 코드는 IV의 키를 사용합니다.

    private static AesCryptoServiceProvider GetProvider(byte[] key)
    {
        //Set up the encryption objects
        AesCryptoServiceProvider result = new AesCryptoServiceProvider();
        byte[] RealKey = Encryptor.GetKey(key, result);
        result.Key = RealKey;
        result.IV = RealKey;
        return result;
    }

    그리고

    private static byte[] GetKey(byte[] suggestedKey, AesCryptoServiceProvider p)
    {
        byte[] kRaw = suggestedKey;
        List kList = new List();
        for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8 )
        {
            kList.Add(kRaw[i % kRaw.Length]);
        }
        byte[] k = kList.ToArray();
        return k;
    }

    아마도 : kList.Add(kRaw[(i / 8) % kRaw.Length]);. 그렇지 않으면 길이 % 8 == 0이 같은 문자를 반복적으로 사용하는 키, doh!

    따라서 .NET에서 사용하는 IV (및 키)는 다음과 같습니다. hleolhleolhleolh. 이것은 API의 일부가 아니라 오히려 당신이 지적한 래퍼 코드 때문입니다 (심각한 버그가 있습니다 ...).

  • iPhone 코드는 IV에 0을 사용합니다.

    // Initialization vector; dummy in this case 0's.
    uint8_t iv[kChosenCipherBlockSize];
    memset((void *) iv, 0x0, (size_t) sizeof(iv));
  • OpenSSL은 기본적으로 무작위로 생성 된 소금을 선출합니다 (출력이 더 길어집니다!).

OpenSSL 출력은 임의의 초기화 벡터를 선점하고 있기 때문에 더 안전합니다. Base64 디코딩 문자열의 처음 몇 바이트는 "Salted__"인 것 같습니다. 또한 OpenSSL에 소금 (-nosalt)을 사용하지 말고 IV (-iv)를 제공하도록 요청할 수도 있습니다.

기본적으로 OpenSSL, .NET 및 iPhone은 동일한 암호화를 사용하고 있으므로 암호화 키 및 초기화 벡터로 API를 초기화하는 방법에주의해야합니다.

다른 팁

C#에서

void test(){
   string ctB64 = encrypt("hola");
   Console.WriteLine(ctB64);  // the same as in objective-c
}

string encrypt(string input)
        {
            try
            {
                // Create a new instance of the AesManaged class.  This generates a new key and initialization vector (IV).
                AesManaged myAes = new AesManaged();

                // Override the cipher mode, key and IV
                myAes.Mode = CipherMode.CBC;
                myAes.IV = new byte[16] { 0x10, 0x16, 0x1F, 0xAD, 0x10, 0x10, 0xAA, 0x22, 0x12, 0x51, 0xF1, 0x1E, 0x15, 0x11, 0x1B, 0x10 }; // must be the same as in objective-c
                myAes.Key = Encoding.UTF8.GetBytes(“0123456789123456”);
                //CipherKey;  // Byte array representing the key
                myAes.Padding = PaddingMode.PKCS7;

                // Create a encryption object to perform the stream transform.
                ICryptoTransform encryptor = myAes.CreateEncryptor();

                // perform the encryption as required...
                MemoryStream ms = new MemoryStream();
                CryptoStream ct = new CryptoStream(ms, encryptor, CryptoStreamMode.Write);
                byte[] binput = Encoding.UTF8.GetBytes(input);
                ct.Write(binput, 0, binput.Length);
                ct.Close();
                byte [] result = ms.ToArray();
                return Convert.ToBase64String(result);
            }
            catch (Exception ex)
            {
                // TODO: Log the error 
                Console.WriteLine(ex);
                throw ex;
            }

        }

· Objective-C에서 코코 아산 보안 라이브러리를 추가하십시오 https://github.com/kelp404/cocoasecurity

#import "CocoaSecurity.h"
#import "Base64.h"

…

- (void) test{
 unsigned char bytes[] = { 0x10, 0x16, 0x1F, 0xAD, 0x10, 0x10, 0xAA, 0x22, 0x12, 0x51, 0xF1, 0x1E, 0x15, 0x11, 0x1B, 0x10 }; // must be the same as in c#

    NSData *iv = [NSData dataWithBytesNoCopy:bytes length:16 freeWhenDone:YES];
    NSData* key =   [@"0123456789123456" dataUsingEncoding:NSUTF8StringEncoding];

    CocoaSecurityResult *result = [CocoaSecurity aesEncrypt:@"hola" key:key iv:iv];
   NSLog(@"%@", result.base64); // the same as in c#


    NSData *data = [NSData dataWithBase64EncodedString:result.base64];
    CocoaSecurityResult *result2 = [CocoaSecurity aesDecryptWithData:data key:key iv:iv];

    NSLog(@"%@", result2.utf8String); // show "hola"

}

테스트에서 동일한 AES 키를 사용하고 있다고 확신하십니까? 게시물의 OpenSSL 예제는 오프 스플이 키와 IV를 파생시키는 비밀번호를 사용합니다 (아마도 소금도 사용합니다.

임의의 128 비트 키를 생성 하고이 키를 16 진 형식으로 지정하여 다음과 같이 OpenSSL을 지정하십시오.

openssl enc -aes-128-cbc -a -in hello.txt -K KEY_IN_HEX -iv 0

보안 시스템에서 IV = 0을 사용해서는 안되지만 상호 운용성을 테스트하기 위해서는 괜찮습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top