2010-11-23 48 views
2

我们正在使用此代码在iPhone上使用Objective-C加密:加密在Objective-C /解密在Ruby中使用任何

- (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。

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

回答

5

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

除此之外,它看起来大多好。

这是一个完整的端到端实现,它使用用户密码短语(本例中为'Salamander')的SHA256散列并基于输出。源代码中有一个PHP测试实现,重构密钥然后在给出最终输出之前修剪PKCS7填充。 Ruby中的解密程序如下,PKCS7填充删除将由OpenSSL :: Cipher自动进行。

在这里你去:在Ruby中

// 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[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/"; 
    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 

解密上面的输出:

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

我该如何证明这个加密/解密工作,在[link](http://www.tools4noobs.com/online_tools/decrypt/)工具中在线证明?因为当我用文字3o4ARWOxwmLEPgq3SJ3A2ws7sUSxMvWSKbbs + oABsOcywk + ​​9qPBoDjhLAfAW/n28pbnsT2w5QMSye6pz3Lz8xmg5BYL8HdfKwbS9EpTbaUc =“火蜥蜴”为重点,和方法的Rijndael-128 CBC尝试,它doesn't显示正确解密 – Evaristoyok 2012-04-10 18:29:18

+0

好,我做到了,但是当我在PHP与解密你给的代码,大部分时间都是活的字符垃圾,在php中它看起来像是正方形[] – Evaristoyok 2012-04-10 21:10:29

0

我还没有做过你正在做的事情,至少不是确切的,但以下可能值得一试。

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

我认为乔纳斯可能是正确的使用Rijndael。我记得与Crypt合作,并要求指定密码。

0

你还可使用下列库,提供内置的AES-256-CBC加密和Base64编码,您可以在两个平台上快速使用:

红宝石

https://github.com/Gurpartap/aescrypt

这里是你将如何使用AESCrypt红宝石宝石:

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

希望它有帮助!