代码之家  ›  专栏  ›  技术社区  ›  ConsultUtah

在objective-c中加密/在ruby中使用任何东西解密

  •  2
  • ConsultUtah  · 技术社区  · 14 年前

    我们在iPhone上使用此代码以Objective-C加密:

    - (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;
    }
    

    并尝试在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一起工作。

    有人知道如何让这些工作在一起吗?

    4 回复  |  直到 12 年前
        1
  •  5
  •   par    14 年前

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

    除此之外,它看起来还不错。

    这是一个完整的端到端实现,使用用户密码短语的sha256散列(在本例中是“salamander”)并基于64'输出。源代码中有一个PHP测试实现,它重建密钥,然后在给出最终输出之前修剪pkcs7填充。下面是Ruby中的一个解密程序,openssl::cipher会自动删除pkcs7填充。

    干得好:

    // 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"
    
        2
  •  0
  •   Jonas Elfström    14 年前

    我没有做你正在做的事情,至少不完全是这样,但是下面的内容值得一试。

    require 'crypt/rijndael'
    require 'Base64'
    rijndael = Crypt::Rijndael.new("samepassword")
    decryptedBlock = rijndael.decrypt_block(Base64.decode64("encrypted-b64-encoded-data"))
    
        3
  •  0
  •   Montana Harkin    14 年前

    我认为乔纳斯使用Rijndael可能是正确的。我记得和crypt一起工作,它需要指定密码。

        4
  •  0
  •   Gurpartap Singh    12 年前

    您还可以使用以下libs,提供内置的aes-256-cbc密码和base64编码,可以在两个平台上快速使用:

    红宝石

    https://github.com/Gurpartap/aescrypt

    下面是您如何使用aescrypt ruby gem:

    message = "top secret message"
    password = "p4ssw0rd"
    
    # Encrypting
    encrypted_data = AESCrypt.encrypt(message, password)
    
    # Decrypting
    message = AESCrypt.decrypt(encrypted_data, password)
    

    目标-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];
    

    希望有帮助!