c# - AES - c# 加密和 objective-c 解密不起作用

标签 c# ios objective-c cryptography aes

我正在尝试在 Objective c 和 C# 中使用 Fixed KeyIV 实现 AES 加密,当我在 C# 中加密并尝试在 Objective C 中解密它不起作用。 你能检查一下并让我知道我做错了什么吗。

C#代码

byte[] strKey = Convert.FromBase64String("CAshKUlVCllbEwPmzS4cTg==");
byte[] strIV = Convert.FromBase64String("HDAxBBlsKyVeIuS63kdCjg==");
byte[] strOutput = EncryptStringToBytes_Aes("satishsatyam", strKey, strIV);
string strOutput1 = ByteToString(strOutput);//i6BMzAlcnz6Z5dQKWkio7A==

static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
    {
        byte[] encrypted;
        // Create an Aes object 
        // with the specified key and IV. 
        using (Aes aesAlg = Aes.Create())
        {
            aesAlg.Mode = CipherMode.ECB;
            aesAlg.Padding = PaddingMode.PKCS7;
            aesAlg.KeySize = 256;
            aesAlg.BlockSize = 128;

            // Create an encryptor to perform the stream transform.
            ICryptoTransform encryptor = aesAlg.CreateEncryptor(Key, IV);

            // Create the streams used for encryption. 
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //Write all data to the stream.
                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }
        return encrypted;
    }
private string ByteToString(byte[] objByte)
    {
        string strOutput = Convert.ToBase64String(objByte);

        return strOutput;
    }

objective-c

//
//  CryptLib.h
//

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

@interface CryptLib : NSObject

-  (NSData *)encrypt:(NSData *)plainText key:(NSString *)key iv:(NSString *)iv;
-  (NSData *)decrypt:(NSData *)encryptedText key:(NSString *)key iv:(NSString *)iv;
-  (NSData *)generateRandomIV:(size_t)length;
-  (NSString *) md5:(NSString *) input;
-  (NSString*) sha256:(NSString *)key length:(NSInteger) length;

@end


#import "CryptLib.h"
#import "NSData+Base64.h"

@implementation CryptLib


-(NSData *)decrypt:(NSData *)encryptedText key:(NSString *)key iv:(NSString *)iv {
    char keyPointer[kCCKeySizeAES256+2],// room for terminator (unused) ref: https://devforums.apple.com/message/876053#876053
    ivPointer[kCCBlockSizeAES128+2];
    BOOL patchNeeded;

    patchNeeded = ([key length] > kCCKeySizeAES256+1);
    if(patchNeeded)
    {
        NSLog(@"Key length is longer %lu", (unsigned long)[[[CryptLib alloc] md5:key] length]);
        key = [key substringToIndex:kCCKeySizeAES256]; // Ensure that the key isn't longer than what's needed (kCCKeySizeAES256)
    }

    [key getCString:keyPointer maxLength:sizeof(keyPointer) encoding:NSUTF8StringEncoding];
    [iv getCString:ivPointer maxLength:sizeof(ivPointer) encoding:NSUTF8StringEncoding];

    if (patchNeeded) {
        keyPointer[0] = '\0';  // Previous iOS version than iOS7 set the first char to '\0' if the key was longer than kCCKeySizeAES256
    }

    NSUInteger dataLength = [encryptedText length];

    //see https://developer.apple.com/library/ios/documentation/System/Conceptual/ManPages_iPhoneOS/man3/CCryptorCreateFromData.3cc.html
    // For block ciphers, the output size will always be less than or equal to the input size plus the size of one block.
    size_t buffSize = dataLength + kCCBlockSizeAES128;

    void *buff = malloc(buffSize);

    size_t numBytesEncrypted = 0;
    //refer to http://www.opensource.apple.com/source/CommonCrypto/CommonCrypto-36064/CommonCrypto/CommonCryptor.h
    //for details on this function
    //Stateless, one-shot encrypt or decrypt operation.
    CCCryptorStatus status = CCCrypt(kCCDecrypt,/* kCCEncrypt, etc. */
                                     kCCAlgorithmAES128, /* kCCAlgorithmAES128, etc. */
                                     kCCOptionPKCS7Padding, /* kCCOptionPKCS7Padding, etc. */
                                     keyPointer, kCCKeySizeAES256,/* key and its length */
                                     ivPointer, /* initialization vector - use same IV which was used for decryption */
                                     [encryptedText bytes], [encryptedText length], //input
                                     buff, buffSize,//output
                                     &numBytesEncrypted);
    if (status == kCCSuccess) {
        return [NSData dataWithBytesNoCopy:buff length:numBytesEncrypted];
    }

    free(buff);
    return nil;
}

#import "ViewController.h"
#import "CryptLib.h"


@interface ViewController ()

@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    libr = [[CryptLib alloc]init];

     NSString *inputString = @"sample testing"; // this is the text that you want to encrypt.
     NSLog(@"inputString : %@", inputString); //print the inputString text

     NSString * _key = @"shared secret"; //secret key for encryption. To make encryption stronger, we will not use this key directly. We'll first hash the key next step and then use it.

    // _key = [[CryptLib alloc] sha256:_key length:32]; //this is very important, 32 bytes = 256 bit
    _key = @"CAshKUlVCllbEwPmzS4cTg==";
     NSLog(@"_key data:: %@", _key); //print the _key text

   // NSString * iv =  [[[libr generateRandomIV:11]  base64EncodingWithLineLength:0] substringToIndex:16]; //Here we are generating random initialization vector (iv). Length of this vector = 16 bytes = 128 bits
    NSString * iv = @"HDAxBBlsKyVeIuS63kdCjg==";
    NSLog(@"iv data:: %@", iv); //print the iv text

    NSData *encryptedData = [libr decrypt:[@"i6BMzAlcnz6Z5dQKWkio7A==" dataUsingEncoding:NSUTF8StringEncoding]  key:_key iv:iv];
    NSString * decryptedText = [[NSString alloc] initWithData:encryptedData encoding:NSUTF8StringEncoding];
    NSLog(@"decrypted data:: %@", decryptedText); //print the decrypted text

}

适用于ios/Android,c#的跨平台示例代码

最佳答案

第一步是以十六进制记录加密调用前后的所有输入和输出,以便验证它们是否相同。
还要验证所有参数是否相同且正确,这可能需要阅读文档以确定默认值。

实际的加密函数很简单,只是一个函数调用,没有什么神秘的东西可以运行,只要输入正确即可。

  1. 您没有向 C# 和 ObjC 代码提供相同的参数。 C#是ECB模式,ObjC是CBC模式(默认)。
    使用 CBC 模式。

  2. key Base64:“CAshKUlVCllbEwPmzS4cTg==”
    是十六进制 080B212949550A595B1303E6CD2E1C4E
    这是 16 个字节。
    在 C# 和 ObjC 中,您将 key 大小指定为 256 位(32 字节):分别为 aesAlg.KeySize = 256;kCCKeySizeAES256
    对于 128 位 key ,将 key 大小指定为 128 位。

  3. 在 ObjC 代码中,您没有对 key 和 iv 进行 Base64 解码。

  4. 没有理由使用第 3 方 Base64 库。

更新了示例代码,没有错误检查:不适用于生产:

// First convert Base64 strings to data
NSString *stringIn = @"satishsatyam";
NSData *dataIn     = [stringIn dataUsingEncoding:NSUTF8StringEncoding];
NSData *iv         = [[NSData alloc] initWithBase64EncodedString:@"HDAxBBlsKyVeIuS63kdCjg==" options:0];
NSData *key        = [[NSData alloc] initWithBase64EncodedString:@"CAshKUlVCllbEwPmzS4cTg==" options:0];

// Encryption
size_t         encryptBytes = 0;
NSMutableData *encrypted  = [NSMutableData dataWithLength:stringIn.length + kCCBlockSizeAES128];
CCCrypt(kCCEncrypt,
        kCCAlgorithmAES,
        kCCOptionPKCS7Padding, // CBC is the default mode
        key.bytes, kCCKeySizeAES128,
        iv.bytes,
        dataIn.bytes, dataIn.length,
        encrypted.mutableBytes, encrypted.length,
        &encryptBytes);
encrypted.length = encryptBytes;
NSLog(@"encrypted hex:    %@", encrypted);
NSLog(@"encrypted Base64: %@", [encrypted base64EncodedStringWithOptions:0]);

// Decryption
size_t         decryptBytes = 0;
NSMutableData *decrypted  = [NSMutableData dataWithLength:encrypted.length];
CCCrypt(kCCDecrypt,
        kCCAlgorithmAES,
        kCCOptionPKCS7Padding, // CBC is the default mode
        key.bytes, kCCKeySizeAES128,
        iv.bytes,
        encrypted.bytes, encrypted.length,
        decrypted.mutableBytes, decrypted.length,
        &decryptBytes);
decrypted.length = decryptBytes;

NSLog(@"decrypted in hex: %@", decrypted);
NSLog(@"decrypted string: %@", [[NSString alloc] initWithData:decrypted encoding: NSUTF8StringEncoding]);

输出:

encrypted as hex: cbdb58fe ad464126 ea90252b 2ff52276
encrypted Base64: y9tY/q1GQSbqkCUrL/Uidg==
decrypted as hex: 73617469 73687361 7479616d
decrypted string: satishsatyam

关于c# - AES - c# 加密和 objective-c 解密不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35297582/

相关文章:

c# - .NET StackOverflow 异常更有可能出现在一台 PC 上

ios - 实现类似行为的应用程序图标

ios - 异步调用对象的正确方式?

ios - 在 cocos2d v3 中创建填充图像图案的图层的最简单方法

ios - 连接wifi时获取ios设备的IP地址

c# - Excel INT等效

c# - 动态 Linq to 实体排序与分页

c# - 我可以避免对简单的 Linq to Entities 投影进行嵌套 SQL 查询吗?

ios - 使用基于之前选择的内容的选择器 View

ios - 压缩 UIImage