Encrypt in Objective-C / Decrypt in Ruby using anything

前端 未结 4 1209
梦如初夏
梦如初夏 2021-01-01 07:26

We are using this code to encrypt in Objective-C on the iPhone:

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


        
相关标签:
4条回答
  • 2021-01-01 07:36

    I haven't done what you are doing, at least not exactly, but the following could be worth a try.

    require 'crypt/rijndael'
    require 'Base64'
    rijndael = Crypt::Rijndael.new("samepassword")
    decryptedBlock = rijndael.decrypt_block(Base64.decode64("encrypted-b64-encoded-data"))
    
    0 讨论(0)
  • 2021-01-01 07:45

    You could as well use the following libs providing in-built AES-256-CBC cipher and Base64 encoding that you can use across both platforms quickly:

    Ruby

    https://github.com/Gurpartap/aescrypt

    Here's how you would use the AESCrypt Ruby gem:

    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

    Here's how you would use the AESCrypt Objective-C class:

    NSString *message = @"top secret message";
    NSString *password = @"p4ssw0rd";
    
    // Encrypting
    NSString *encryptedData = [AESCrypt encrypt:message password:password];
    
    // Decrypting
    NSString *message = [AESCrypt decrypt:encryptedData password:password];
    

    Hope it helps!

    0 讨论(0)
  • 2021-01-01 07:50

    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"
    
    0 讨论(0)
  • 2021-01-01 07:55

    I think Jonas might be correct about using Rijndael. I remember working with Crypt and it requiring the cypher to be specified.

    0 讨论(0)
提交回复
热议问题