加密在Objective-C /解密Ruby中使用任何东西 [英] Encrypt in Objective-C / Decrypt in Ruby using anything

查看:160
本文介绍了加密在Objective-C /解密Ruby中使用任何东西的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

   - (NSMutableData *)加密AES:( 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;
}
返回NULL;
}

并尝试使用Ruby中的OpenSSL进行解密:

  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

我愿意使用任何红宝石宝石。我可以控制双方,但是我无法让它与EzCrypto,openssl或crypt一起工作。



任何人都知道如何让这些工作在一起

解决方案

您的代码泄漏了第一个输出分配。



此外,它看起来大部分是可以的。



这是一个完整的端到端实现,使用用户密码(在这种情况下是Salamander)的SHA256哈希值, base64的输出。源中有一个PHP测试实现重建密钥,然后在给出最终输出之前修剪PKCS7填充。 Ruby中的解密器就是由OpenSSL :: Cipher自动执行的PKCS7填充删除。



这里你去:

  // iOS的加密类别

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


@interface NSData(Crypto)

- (NSData *)aesEncryptedDataWithKey:(NSData *)键;
- (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;

//确保有数据加密
err =(plainTextLength = [self length])== 0;

//通过SHA256传递用户密码以获取密钥数据的32个字节
//。使用AES256键的所有32个字节,或仅对AES128的
//第16位。
if(!err){
switch((keyLength = [key length])){
case kCCKeySizeAES128:
case kCCKeySizeAES256:break;

//无效键大小
默认值:err = 1;打破;
}
}

//创建一个带有pad字节空间的输出缓冲区
if(!err){
bufferSize = kCCBlockSizeAES128 + plainTextLength + kCCBlockSizeAES128 ; // iv + cipher + padding

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

//加密数据
if(!err){
srandomdev();

//生成一个随机的iv,并将其添加到输出缓冲区。
//解密器需要注意这一点。 (i = 0; i 缓冲区[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拥有缓冲区的所有权,并释放拥有该NSData对象的
//。
return [NSData dataWithBytesNoCopy:buffer length:bufferSize + kCCBlockSizeAES128];
}

- (NSString *)base64Encoding {
char * encoded,* r;
const char eTable [] =ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 + /;
无符号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 = 1/3)+(1%3?1:0))+ 1);

if(!encoded)return nil; (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];

自由(编码);

返回结果;
}

@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)应用程序:(UIApplication *)应用程序didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSData * plain = [@This是对紧急广播系统的测试。 dataUsingEncoding:NSUTF8StringEncoding];
NSData * key = [NSData dataWithBytes:[[@Salamandersha256] bytes] length:kCCKeySizeAES128];
NSData * cipher = [plain aesEncryptedDataWithKey:key];
NSString * base64 = [cipher base64Encoding];

NSLog(@cipher:%@,base64);

//将base64的密码填入decrypt.php:
// http://localhost/~par/decrypt.php?cipher =< base64_output>

/ *
<?php
标题(content-type:text / plain);

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

echocipher:$ cipher\\\
;

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

//使用全键(全32字节)为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\\\
,$ plainText);
?>
* /

返回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)
#不分片AES256的SHA256输出
aes.key =(Digest :: SHA256.digest('Salamander')).slice(0 ,16)

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

返回aes.update(cipher)+ aes.final
end

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

打印解密(文本)+\\\


We are using this code to encrypt in Objective-C on the 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;
}

And trying to decrypt that using OpenSSL in Ruby as so:

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'm willing to use ANY ruby gem. I can control both sides, but I haven't been able to get this to work with EzCrypto, openssl, or crypt.

Anyone know how to get these to work together?

解决方案

Your code is leaking the first allocation of output.

Besides that it looks mostly ok.

This is a complete end-to-end implementation using a SHA256 hash of the user's passphrase (in this case 'Salamander') and base64'ing the output. There is a PHP test implementation in the source that reconstructs the key then trims the PKCS7 padding before giving final output. A decryptor in Ruby follows, the PKCS7 padding removal happens automatically by the OpenSSL::Cipher.

Here you go:

// 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

Decryption of the output of the above in 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"

这篇关于加密在Objective-C /解密Ruby中使用任何东西的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆