我正在尝试为一些使用Crypto ++库的加密操作制作一个Objective-C包装类。我有几个问题,
这是我正在使用的代码
- (void)testSerpentEncryptonMechanism
{
byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ];
::memset( key, 0x50 , CryptoPP::Serpent::MAX_KEYLENGTH );
::memset( iv, 0x10, CryptoPP::Serpent::BLOCKSIZE );
NSString *andThisShalBeEncrypted = @"Serpentine and black...";
NSLog(@"will encrypt %@",andThisShalBeEncrypted);
NSString *encrypted = [self encryptWithSerpentString:andThisShalBeEncrypted withKey:key];
NSLog(@"encrypted:%@",encrypted);
NSString *decrypted = [self decryptWithSerpentString:encrypted withKey:key andIV:iv];
NSLog(@"decrypted: %@",decrypted);
}
- (NSString *)encryptWithSerpentString:(NSString *)plaintext withKey:(byte[])keyArray
{
std::string ptext = [plaintext UTF8String];
std::string ciphertext;
byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ];
::memset( key, 0x50 , CryptoPP::Serpent::MAX_KEYLENGTH );
::memset( iv, 0x10, CryptoPP::Serpent::BLOCKSIZE );
CryptoPP::Serpent::Encryption serpentEncryptor (key, CryptoPP::Serpent::MAX_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcSerpentEncryptor (serpentEncryptor, iv);
CryptoPP::StreamTransformationFilter stfSerpentEncryptor(cbcSerpentEncryptor, new CryptoPP::StringSink (ciphertext));
stfSerpentEncryptor.Put( reinterpret_cast<const unsigned char*>( ptext.c_str() ), ptext.length() + 1);
stfSerpentEncryptor.MessageEnd();
std::string finalCT;
CryptoPP::StringSource base64Encoder (ciphertext, true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(finalCT)));
return @(finalCT.c_str());
}
- (NSString *)decryptWithSerpentString:(NSString *)ciphertext withKey:(byte[])keyArray andIV:(byte[])initializationVector
{
std::string ctext;
std::string plaintext;
byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ];
// ::memset( key, &keyArray , CryptoPP::Serpent::MAX_KEYLENGTH );
// ::memset( iv, (byte[])initializationVector, CryptoPP::Serpent::BLOCKSIZE );
::memset( key, 0x50 , CryptoPP::Serpent::MAX_KEYLENGTH );
::memset( iv, 0x10, CryptoPP::Serpent::BLOCKSIZE );
// decode from base64
std::string encoded = [ciphertext UTF8String];
CryptoPP::StringSource base64Encoder (encoded, true, new CryptoPP::Base64Decoder(new CryptoPP::StringSink(ctext)));
CryptoPP::Serpent::Decryption serpentDecryptor (key, CryptoPP::Serpent::MAX_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcSerpentDecryptor (serpentDecryptor, iv);
CryptoPP::StreamTransformationFilter stfSerpentDecryptor(cbcSerpentDecryptor, new CryptoPP::StringSink (ctext));// crash
stfSerpentDecryptor.Put( reinterpret_cast<const unsigned char*>( ctext.c_str() ), ctext.length() + 1);
stfSerpentDecryptor.MessageEnd();
return @(ctext.c_str());
}
1)如何将key / IV作为方法参数传递?请参阅注释后的代码,但不起作用......
2)尝试decrpyt时发生了崩溃
libc ++ abi.dylib:以CryptoPP类型的未捕获异常终止:: InvalidCiphertext:StreamTransformationFilter:密文长度不是块大小的倍数
为什么呢?我认为解密是自动的,加密将相应地填充明文... 我还想在方法中添加一个HMAC ...这将在加密后添加并在解密前检查,对吗?
答案 0 :(得分:2)
要获得填充,您必须自己完成或拥有支持标准填充的API,例如PKCS7。基本加密,流加密除外,是基于块的,在较低级别必须有完整的块。一些更高级别的API提供填充。
我传递密钥,iv和数据as NSData *
并以data.bytes
的形式访问字节
对于密码输出数据:
NSMutableData *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];
// ...
dataOut.mutableBytes,
dataOut.length,
&cryptBytes
// ...
dataOut.length = cryptBytes;
我会将我的API调用类似于:
- (NSString *)encryptWithSerpentText:(NSString *)text key:(NSData *)key iv:(NSData *)iv;
Mac很好,但你将如何验证它。最好研究身份验证的最佳实践。
对于HMAC,只需使用Apple提供的CommonCrypto库。 CommonCrypto还支持:AES128,DES,3DES,CAST,RC4和Blowfish,但不支持Serpent。
最后,为了让事情能够记录服务器和客户端中的每一步,这样就可以找到失败的错误步骤。在这种情况下,针对混合Objective-C / C ++版本的直接C ++版本。