Зашифруйте в Objective-C / Расшифруйте в Ruby, используя что-либо - PullRequest
2 голосов
/ 23 ноября 2010

Мы используем этот код для шифрования в Objective-C на iPhone:

- (NSMutableData*) EncryptAES: (NSString *) key
{
    char keyPtr[kCCKeySizeAES128+1];
    bzero( keyPtr, sizeof(keyPtr) );

    [key getCString: keyPtr maxLength: sizeof(keyPtr) encoding: NSUTF8StringEncoding];
    size_t numBytesEncrypted = 0;

    NSUInteger dataLength = [self length];

    size_t bufferSize = dataLength + kCCBlockSizeAES128;
        void *buffer = malloc(bufferSize);


    NSMutableData *output = [[NSData alloc] init];


    CCCryptorStatus result = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                     keyPtr, kCCKeySizeAES128,
                                     NULL,
                                     [self mutableBytes], [self length],
                                     buffer, bufferSize,
                                     &numBytesEncrypted );

    output = [NSMutableData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        if( result == kCCSuccess )
        {
                return output;
        }
    return NULL;
}

И пытаемся расшифровать это с помощью OpenSSL в Ruby следующим образом:

aes = OpenSSL::Cipher::Cipher.new('AES-128-CBC')
aes.decrypt
aes.padding = 1
aes.iv = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0].pack('c*')
aes.key = key
result = aes.update(d) + aes.final

I 'Я готов использовать ЛЮБОЙ рубиновый камень.Я могу контролировать обе стороны, но я не смог заставить это работать с EzCrypto, openssl или crypt.

Кто-нибудь знает, как заставить их работать вместе?

Ответы [ 4 ]

5 голосов
/ 01 декабря 2010

Ваш код пропускает первое распределение вывода.

Кроме того, это выглядит в основном нормально.

Это полная сквозная реализация, использующая хэш SHA256 парольной фразы пользователя (в данном случае «Salamander») и base64, выводящий результат. В исходном коде есть реализация теста PHP, которая восстанавливает ключ, а затем обрезает заполнение PKCS7 перед выдачей окончательного результата. Далее следует расшифровка в Ruby, удаление отступов PKCS7 происходит автоматически с помощью OpenSSL :: Cipher.

Вот, пожалуйста,

// Crypto categories for iOS

#import <CommonCrypto/CommonCryptor.h>
#import <CommonCrypto/CommonDigest.h>


@interface NSData( Crypto )

- (NSData *) aesEncryptedDataWithKey:(NSData *) key;
- (NSString *) base64Encoding;

@end


@interface NSString( Crypto )

- (NSData *) sha256;

@end


// --------


@implementation NSData( Crypto )

- (NSData *) aesEncryptedDataWithKey:(NSData *) key {
    unsigned char               *buffer = nil;
    size_t                      bufferSize;
    CCCryptorStatus             err;
    NSUInteger                  i, keyLength, plainTextLength;

    // make sure there's data to encrypt
    err = ( plainTextLength = [self length] ) == 0;

    // pass the user's passphrase through SHA256 to obtain 32 bytes
    // of key data.  Use all 32 bytes for an AES256 key or just the
    // first 16 for AES128.
    if ( ! err ) {
        switch ( ( keyLength = [key length] ) ) {
            case kCCKeySizeAES128:
            case kCCKeySizeAES256:                      break;

            // invalid key size
            default:                    err = 1;        break;
        }
    }

    // create an output buffer with room for pad bytes
    if ( ! err ) {
        bufferSize = kCCBlockSizeAES128 + plainTextLength + kCCBlockSizeAES128;     // iv + cipher + padding

        err = ! ( buffer = (unsigned char *) malloc( bufferSize ) );
    }

    // encrypt the data
    if ( ! err ) {
        srandomdev();

        // generate a random iv and prepend it to the output buffer.  the
        // decryptor needs to be aware of this.
        for ( i = 0; i < kCCBlockSizeAES128; ++i ) buffer[ i ] = random() & 0xff;

        err = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
            [key bytes], keyLength, buffer, [self bytes], plainTextLength,
            buffer + kCCBlockSizeAES128, bufferSize - kCCBlockSizeAES128, &bufferSize );
    }

    if ( err ) {
        if ( buffer ) free( buffer );

        return nil;
    }

    // dataWithBytesNoCopy takes ownership of buffer and will free() it
    // when the NSData object that owns it is released.
    return [NSData dataWithBytesNoCopy: buffer length: bufferSize + kCCBlockSizeAES128];
}

- (NSString *) base64Encoding {
    char                    *encoded, *r;
    const char              eTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    unsigned                i, l, n, t;
    UInt8                   *p, pad = '=';
    NSString                *result;

    p = (UInt8 *) [self bytes];
    if ( ! p || ( l = [self length] ) == 0 ) return @"";
    r = encoded = malloc( 4 * ( ( n = l / 3 ) + ( l % 3 ? 1 : 0 ) ) + 1 );

    if ( ! encoded ) return nil;

    for ( i = 0; i < n; ++i ) {
        t  = *p++ << 16;
        t |= *p++ << 8;
        t |= *p++;

        *r++ = eTable[ t >> 18 ];
        *r++ = eTable[ t >> 12 & 0x3f ];
        *r++ = eTable[ t >>  6 & 0x3f ];
        *r++ = eTable[ t       & 0x3f ];
    }

    if ( ( i = n * 3 ) < l ) {
        t = *p++ << 16;

        *r++ = eTable[ t >> 18 ];

        if ( ++i < l ) {
            t |= *p++ << 8;

            *r++ = eTable[ t >> 12 & 0x3f ];
            *r++ = eTable[ t >>  6 & 0x3f ];
        } else {
            *r++ = eTable[ t >> 12 & 0x3f ];
            *r++ = pad;
        }

        *r++ = pad;
    }

    *r = 0;

    result = [NSString stringWithUTF8String: encoded];

    free( encoded );

    return result;
}

@end


@implementation NSString( Crypto )

- (NSData *) sha256 {
    unsigned char               *buffer;

    if ( ! ( buffer = (unsigned char *) malloc( CC_SHA256_DIGEST_LENGTH ) ) ) return nil;

    CC_SHA256( [self UTF8String], [self lengthOfBytesUsingEncoding: NSUTF8StringEncoding], buffer );

    return [NSData dataWithBytesNoCopy: buffer length: CC_SHA256_DIGEST_LENGTH];
}

@end


// -----------------


@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    
    NSData              *plain = [@"This is a test of the emergency broadcast system." dataUsingEncoding: NSUTF8StringEncoding];
    NSData              *key = [NSData dataWithBytes: [[@"Salamander" sha256] bytes] length: kCCKeySizeAES128];
    NSData              *cipher = [plain aesEncryptedDataWithKey: key];
    NSString            *base64 = [cipher base64Encoding];

    NSLog( @"cipher: %@", base64 );

    // stuff the base64'ed cipher into decrypt.php:
    // http://localhost/~par/decrypt.php?cipher=<base64_output>

/*
<?php
    header( "content-type: text/plain" );

    if ( ! ( $cipher = $_GET[ 'cipher' ] ) ) {
        echo "no cipher parameter found";
        return;
    }

    echo "cipher: $cipher\n";

    $cipher = base64_decode( $cipher );
    $iv = substr( $cipher, 0, 16 );
    $cipher = substr( $cipher, 16 );

    // use the full key (all 32 bytes) for aes256
    $key = substr( hash( "sha256", "Salamander", true ), 0, 16 );

    $plainText = mcrypt_decrypt( MCRYPT_RIJNDAEL_128, $key, $cipher, MCRYPT_MODE_CBC, $iv );
    $plainTextLength = strlen( $plainText );

    // strip pkcs7 padding
    $padding = ord( $plainText[ $plainTextLength - 1 ] );
    $plainText = substr( $plainText, 0, -$padding );

    printf( "plaintext: %s\n", $plainText );
?>
*/

    return YES;
}

@end

Расшифровка выходных данных в Ruby:

require 'base64'
require 'openssl'

def decrypt( cipherBase64 )
    cipher = Base64.decode64( cipherBase64 )

    aes = OpenSSL::Cipher::Cipher.new( "aes-128-cbc" ).decrypt
    aes.iv = cipher.slice( 0, 16 )
    # don't slice the SHA256 output for AES256
    aes.key = ( Digest::SHA256.digest( 'Salamander' ) ).slice( 0, 16 )

    cipher = cipher.slice( 16..-1 )

    return aes.update( cipher ) + aes.final
end

text = '3o4ARWOxwmLEPgq3SJ3A2ws7sUSxMvWSKbbs+oABsOcywk+9qPBoDjhLAfAW/n28pbnsT2w5QMSye6pz3Lz8xmg5BYL8HdfKwbS9EpTbaUc='

print decrypt( text ) + "\n"
0 голосов
/ 01 августа 2012

Вы также можете использовать следующие библиотеки, предоставляющие встроенный шифр AES-256-CBC и кодировку Base64, которые можно быстро использовать на обеих платформах:

Ruby

https://github.com/Gurpartap/aescrypt

Вот как вы будете использовать драгоценный камень AESCrypt Ruby:

message = "top secret message"
password = "p4ssw0rd"

# Encrypting
encrypted_data = AESCrypt.encrypt(message, password)

# Decrypting
message = AESCrypt.decrypt(encrypted_data, password)

Objective-C

https://github.com/Gurpartap/AESCrypt-ObjC

Вот как вы будете использоватькласс AESCrypt Objective-C:

NSString *message = @"top secret message";
NSString *password = @"p4ssw0rd";

// Encrypting
NSString *encryptedData = [AESCrypt encrypt:message password:password];

// Decrypting
NSString *message = [AESCrypt decrypt:encryptedData password:password];

Надеюсь, это поможет!

0 голосов
/ 01 декабря 2010

Я думаю, что Джонас может быть прав насчет использования Рейндаэля. Я помню, как работал с Crypt, и для него требовалось указать шифр.

0 голосов
/ 24 ноября 2010

Я не сделал то, что вы делаете, по крайней мере, не совсем, но стоит попробовать следующее.

require 'crypt/rijndael'
require 'Base64'
rijndael = Crypt::Rijndael.new("samepassword")
decryptedBlock = rijndael.decrypt_block(Base64.decode64("encrypted-b64-encoded-data"))
...