2016-08-12 4 views
0

Ich versuche eine Zeichenfolge in einem AES-128 GCM-Format in Ziel c zu verschlüsseln/entschlüsseln. Ich habe überall gesucht, aber ich finde keine funktionierende Lösung.AES 128 GCM Objektiv C osx

Antwort

0

Vor nicht allzu langer Zeit hatte ich ein ähnliches Problem und die beste Antwort, die ich finden konnte, war this one. Zusammengefasst, iOS hat einige Funktionen, um zu tun, was Sie wollen, aber sie sind privat.

Also, bis Apple entscheidet, diese Funktionen freizugeben, entschied ich mich für die Entwicklung meiner eigenen Bibliothek, derzeit in GitHub gespeichert und in CocoaPods verfügbar.

Der Fall, dass Sie beschreiben könnte auf diese Weise realisiert werden:

#import <CommonCrypto/CommonCrypto.h> 
#import "IAGAesGcm.h" 

// For the case you describe, the key length is 128 bits (16 bytes) 
u_char keyBytes[kCCKeySizeAES128] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10}; 
NSData *key = [NSData dataWithBytes:keyBytes length:sizeof(keyBytes)]; 

// GCM recommends a IV size of 96 bits (12 bytes), but you are free 
// to use other sizes 
u_char ivBytes[12] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C}; 
NSData *iv = [NSData dataWithBytes:ivBytes length:sizeof(ivBytes)]; 

NSData *aad = [@"AdditionalAuthenticatedData" dataUsingEncoding:NSUTF8StringEncoding]; 

// Authenticated Encryption Function 
NSData *expectedPlainData = [@"PlainData" dataUsingEncoding:NSUTF8StringEncoding]; 

// The returned ciphered data is a simple class with 2 properties: the actual encrypted data and the authentication tag. 
// The authentication tag can have multiple sizes and it is up to you to set one, in this case the size is 128 bits 
// (16 bytes) 
IAGCipheredData *cipheredData = [IAGAesGcm cipheredDataByAuthenticatedEncryptingPlainData:expectedPlainData 
                  withAdditionalAuthenticatedData:aad 
                    authenticationTagLength:IAGAuthenticationTagLength128 
                    initializationVector:iv 
                         key:key 
                        error:nil]; 

// Authenticated Decryption Function 
NSData *plainData = [IAGAesGcm plainDataByAuthenticatedDecryptingCipheredData:cipheredData 
               withAdditionalAuthenticatedData:aad 
                 initializationVector:iv 
                      key:key 
                     error:nil]; 

XCTAssertEqualObjects(expectedPlainData, plainData); 

Hoffnung dieser Code eine Hilfe ist.

zu beenden (und dank zaph dies für die Erwähnung), habe ich eine Benchmarking dieses Codes nicht durchgeführt, so davon ausgehen, dass es langsam ist. Ich beabsichtige, es zu benutzen, um Token in einer JWE Schnur zu entschlüsseln und nur von Zeit zu Zeit, ich empfehle nicht irgendetwas, das mehr als das erfordert.

Grüße.

+0

Beachten Sie, dass das Apple AES-GCM etwas hirntot ist, es behandelt keine damit verbundenen Daten. Selbst Apple gibt zu, dass es sich um eine schlechte Implementierung handelt, die nur ihren Anforderungen entspricht. Übrigens, haben Sie irgendwelche Benchmarks? – zaph

+0

Ich war mir dessen nicht bewusst, vielen Dank für die Informationen. Nun, es war eine _learning_ Erfahrung :). Über die Leistung habe ich [dieses Dokument] (http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf) im Repo verlinkt, es weist auf einen effizienten auf Weg, diesen Algorithmus zu implementieren ... was nicht die Art war, wie ich es kodierte, war ich mehr daran interessiert, einen Code zu schreiben, der leicht zu debuggen ist. Also muss die Leistung _nicht toll_ sein. – Enrique

+0

Gute Arbeit, der Code sieht gut aus. Unglücklicherweise ist es für mich nur eine Arbeit, die ich ausgeben möchte. Die ganze podfile Sache würde mich eine Stunde oder so dauern, um herauszufinden und alles aktualisiert zu bekommen. – zaph

0
/* 
typical GCM use case: sending an authenticated packet 

+--------------+-------+--------------+ 
| header | seq. | Data  | 
+--------------+-------+--------------+ 
     |   |   | 
     |   |   | 
Addtl auth data IV  plain text 
     |   |   | 
     |   |   V 
     |   |  +--------------------+ 
     |   +---->|     | 
     |   |  | GCM encryption  | 
     +---------------->|     | 
     |   |  +--------------------+ 
     |   |   |   | 
     |   |  cipher text Auth tag 
     |   |   |   | 
     V   V   V   V 
+--------------+-------+----------------+---------+ 
| header | seq. | encrypted data | ICV | 
+--------------+-------+----------------+---------+ 
*/ 

#define CCCryptorGCMprologue() CCCryptor *cryptor = getRealCryptor(cryptorRef, 0); \ 
CC_DEBUG_LOG("Entering\n"); \ 
if(!cryptor) return kCCParamError; 

static inline CCCryptorStatus translate_err_code(int err) 
{ 
    if (err==0) { 
     return kCCSuccess; 
    } /*else if(err == CCMODE_INVALID_CALL_SEQUENCE){ //unti we can read error codes from corecrypto 
     return kCCCallSequenceError; 
    } */ else { 
     return kCCUnspecifiedError; 
    } 

} 

CCCryptorStatus 
CCCryptorGCMAddIV(CCCryptorRef cryptorRef, 
        const void  *iv, 
        size_t ivLen) 
{ 
    CCCryptorGCMprologue(); 
    if(ivLen!=0 && iv==NULL) return kCCParamError; 
    //it is okay to call with ivLen 0 and/OR iv==NULL 
    //infact this needs to be done even with NULL values, otherwise ccgcm_ is going to return call sequence error. 
    //currently corecrypto accepts NULL 
    //rdar://problem/23523093 
    int rc = ccgcm_set_iv_legacy(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, ivLen, iv); 
    return translate_err_code(rc); 

} 

//Add additional authentication data 
CCCryptorStatus 
CCCryptorGCMAddAAD(CCCryptorRef cryptorRef, 
        const void  *aData, 
        size_t aDataLen) 
{ 
    CCCryptorGCMprologue(); 
    if(aDataLen!=0 && aData==NULL) return kCCParamError; 
    //it is okay to call with aData zero 
    int rc = ccgcm_gmac(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, aDataLen, aData); 
    return translate_err_code(rc); 
} 

// This is for old iOS5 clients 
CCCryptorStatus 
CCCryptorGCMAddADD(CCCryptorRef cryptorRef, 
        const void  *aData, 
        size_t aDataLen) 
{ 
    return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen); 
} 

// This was a temp mistake in MacOSX8 
CCCryptorStatus 
CCCryptorGCMaddAAD(CCCryptorRef cryptorRef, 
        const void  *aData, 
        size_t aDataLen) 
{ 
    return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen); 
} 

//we are not providing this function to users. 
//The reason is that we don't want to create more liability for ourself 
//and a new interface function just increases the number of APIs 
//without actually helping users 
//User's use the old CCCryptorGCMEncrypt() and CCCryptorGCMDecrypt() 
static CCCryptorStatus gcm_update(CCCryptorRef cryptorRef, 
              const void *dataIn, 
              size_t dataInLength, 
              void *dataOut) 
{ 
    CCCryptorGCMprologue(); 
    if(dataInLength!=0 && dataIn==NULL) return kCCParamError; 
    //no data is okay 
    if(dataOut == NULL) return kCCParamError; 
    int rc = ccgcm_update(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, dataInLength, dataIn, dataOut); 
    return translate_err_code(rc); 
} 


CCCryptorStatus CCCryptorGCMEncrypt(CCCryptorRef cryptorRef, 
            const void *dataIn, 
            size_t dataInLength, 
            void *dataOut) 
{ 
    return gcm_update(cryptorRef, dataIn, dataInLength, dataOut); 

} 



CCCryptorStatus CCCryptorGCMDecrypt(CCCryptorRef cryptorRef, 
            const void *dataIn, 
            size_t dataInLength, 
            void *dataOut) 
{ 
    return gcm_update(cryptorRef, dataIn, dataInLength, dataOut); 
} 


CCCryptorStatus CCCryptorGCMFinal(CCCryptorRef cryptorRef, 
            void *tagOut, 
            size_t *tagLength) 
{ 
    CCCryptorGCMprologue(); 
    if(tagOut == NULL || tagLength == NULL) return kCCParamError; 
    int rc = ccgcm_finalize(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, *tagLength, (void *) tagOut); 
    if(rc == -1) 
     return kCCUnspecifiedError; 
    else 
     return kCCSuccess; //this includes 0 and any error message other than -1 

    // ccgcm_finalize() returns CCMODE_INTEGRITY_FAILURE (-3) if the expected tag is not coppied to the buffer. but that doesn't mean there is an error 
} 


CCCryptorStatus CCCryptorGCMReset(CCCryptorRef cryptorRef) 
{ 
    CCCryptorGCMprologue(); 
    int rc = ccgcm_reset(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm); 
    return translate_err_code(rc); 
} 

CCCryptorStatus CCCryptorGCM(CCOperation op,    /* kCCEncrypt, kCCDecrypt */ 
          CCAlgorithm alg, 
          const void *key, size_t keyLength, /* raw key material */ 
          const void *iv,  size_t ivLen, 
          const void *aData, size_t aDataLen, 
          const void *dataIn, size_t dataInLength, 
          void  *dataOut, 
          void  *tagOut, size_t *tagLength) 

{ 
    CCCryptorRef cryptorRef; 
    CCCryptorStatus retval; 

    CC_DEBUG_LOG("Entering Op: %d Cipher: %d\n", op, alg); 

    retval = CCCryptorCreateWithMode(op, kCCModeGCM, alg, 0, NULL, key, keyLength, 
             NULL, 0, 0, 0, &cryptorRef); 
    if(retval) return retval; 

    //call even with NULL pointer and zero length IV 
    retval = CCCryptorGCMAddIV(cryptorRef, iv, ivLen); 
    if(retval) return retval; 

    retval = CCCryptorGCMaddAAD(cryptorRef, aData, aDataLen); 
    if(retval) return retval; 

    retval = gcm_update(cryptorRef, dataIn, dataInLength, dataOut); 
    if(retval) return retval; 

    retval = CCCryptorGCMFinal(cryptorRef, tagOut, tagLength); 
    CCCryptorRelease(cryptorRef); 

    return retval; 
} 
Verwandte Themen