Pergunta

pode apontar ninguém me na direção certa para ser capaz de criptografar uma string, retornando outra string com os dados criptografados? (Eu tenho tentado com criptografia AES256.) Eu quero escrever um método que leva duas instâncias NSString, sendo um deles a mensagem para criptografar e o ser um 'código de acesso' outro para criptografá-lo com - Eu suspeito que eu teria que gerar a chave de criptografia com o código de acesso, de uma forma que pode ser revertida se a senha for fornecida com os dados criptografados. O método deve retornar um NSString criado a partir dos dados criptografados.

Eu tentei a técnica detalhada em o primeiro comentário sobre este post , mas eu não teve sorte até agora. Da Apple CryptoExercise certamente tem alguma coisa, mas eu não posso fazer o sentido dele. .. Eu já vi muitas referências a CCCrypt , mas falhou em todos os casos que eu usei-o.

Eu também teria que ser capaz de decifrar uma string criptografada, mas espero que seja tão simples como kCCEncrypt / kCCDecrypt.

Foi útil?

Solução

Uma vez que você não postou qualquer código, é difícil saber exatamente quais os problemas que você está encontrando. No entanto, o post que você conectar-se a parece funcionar muito decentemente ... além da vírgula extra em cada chamada para CCCrypt() que causou erros de compilação.

Um comentário mais tarde que post inclui este código adaptado, o que funciona para mim, e parece um pouco mais direto. Se você incluir o seu código para a categoria NSData, você pode escrever algo como isto: (Nota: As chamadas printf() são apenas para demonstrar o estado dos dados em vários pontos - em uma aplicação real, não faria sentido para imprimir tais valores.)

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSString *key = @"my password";
    NSString *secret = @"text to encrypt";

    NSData *plain = [secret dataUsingEncoding:NSUTF8StringEncoding];
    NSData *cipher = [plain AES256EncryptWithKey:key];
    printf("%s\n", [[cipher description] UTF8String]);

    plain = [cipher AES256DecryptWithKey:key];
    printf("%s\n", [[plain description] UTF8String]);
    printf("%s\n", [[[NSString alloc] initWithData:plain encoding:NSUTF8StringEncoding] UTF8String]);

    [pool drain];
    return 0;
}

Diante desse código, eo fato de que dados criptografados não vai sempre se traduz muito bem em um NSString, pode ser mais conveniente para escrever dois métodos que envolvem a funcionalidade que você precisa, em frente e verso ...

- (NSData*) encryptString:(NSString*)plaintext withKey:(NSString*)key {
    return [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
}

- (NSString*) decryptData:(NSData*)ciphertext withKey:(NSString*)key {
    return [[[NSString alloc] initWithData:[ciphertext AES256DecryptWithKey:key]
                                  encoding:NSUTF8StringEncoding] autorelease];
}

Este definitivamente funciona no Snow Leopard, e @Boz relatórios que CommonCrypto é parte do sistema operacional do núcleo no iPhone. Ambos 10.4 e 10.5 têm /usr/include/CommonCrypto, embora 10,5 tem uma página de manual para CCCryptor.3cc e 10,4 não faz, assim YMMV.


EDIT: Veja esta questão de acompanhamento sobre o uso de Base64 codificação para representar dados criptografados bytes como uma string (se desejado), utilizando, conversões sem perdas de segurança.

Outras dicas

Tenho juntos uma coleção de categorias para NSData e NSString que utiliza soluções encontradas em blog de Jeff LaMarche e algumas dicas por Quinn Taylor aqui no estouro de pilha.

Ele usa categorias para estender NSData para fornecer criptografia AES256 e também oferece uma extensão da NSString para BASE64-codificar dados criptografados com segurança para strings.

Aqui está um exemplo para mostrar o uso de criptografia de strings:

NSString *plainString = @"This string will be encrypted";
NSString *key = @"YourEncryptionKey"; // should be provided by a user

NSLog( @"Original String: %@", plainString );

NSString *encryptedString = [plainString AES256EncryptWithKey:key];
NSLog( @"Encrypted String: %@", encryptedString );

NSLog( @"Decrypted String: %@", [encryptedString AES256DecryptWithKey:key] );

Obter o código fonte completo aqui:

https://gist.github.com/838614

Obrigado por todas as dicas úteis!

- Michael

@owlstead, a respeito de seu pedido de "uma variante criptograficamente segura de uma das respostas dadas," consulte RNCryptor . Ele foi projetado para fazer exatamente o que você está solicitando (e foi construída em resposta aos problemas com o código aqui).

RNCryptor utiliza PBKDF2 com sal, proporciona um IV aleatório, e atribui HMAC (também gerados a partir de PBKDF2 com o seu próprio sal. É suporte operação síncronas e assíncronas.

Eu esperei um pouco sobre @QuinnTaylor para atualizar a sua resposta, mas desde que ele não fez, aqui está a resposta um pouco mais claramente e de uma forma que ele irá carregar em XCode7 (e talvez mais). Eu usei isso em um aplicativo de cacau, mas ele provavelmente vai funcionar bem com um aplicativo iOS também. Não tem erros ARC.

Colar antes de qualquer seção @implementation em seu arquivo AppDelegate.m ou AppDelegate.mm.

#import <CommonCrypto/CommonCryptor.h>

@implementation NSData (AES256)

- (NSData *)AES256EncryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES256,
                                     NULL /* initialization vector (optional) */,
                                     [self bytes], dataLength, /* input */
                                     buffer, bufferSize, /* output */
                                     &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

- (NSData *)AES256DecryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self length];

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES256,
                                     NULL /* initialization vector (optional) */,
                                     [self bytes], dataLength, /* input */
                                     buffer, bufferSize, /* output */
                                     &numBytesDecrypted);

    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }

    free(buffer); //free the buffer;
    return nil;
}

@end

Colar essas duas funções na classe @implementation você deseja. No meu caso, eu escolhi @implementation AppDelegate no meu arquivo AppDelegate.mm ou AppDelegate.m.

- (NSString *) encryptString:(NSString*)plaintext withKey:(NSString*)key {
    NSData *data = [[plaintext dataUsingEncoding:NSUTF8StringEncoding] AES256EncryptWithKey:key];
    return [data base64EncodedStringWithOptions:kNilOptions];
}

- (NSString *) decryptString:(NSString *)ciphertext withKey:(NSString*)key {
    NSData *data = [[NSData alloc] initWithBase64EncodedString:ciphertext options:kNilOptions];
    return [[NSString alloc] initWithData:[data AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top