我需要使用PBEWithMD5AndDES JAVA加密方式对我的密码进行加解密PBEWithMD5AndDES , JAVA PBEWithMD5AndDES ,我需要像下面的代码一样快速地进行加密和解密
@implementation CryptoHelper
#pragma mark -
#pragma mark Init Methods
- (id)init
{
if(self = [super init])
{
}
return self;
}
#pragma mark -
#pragma mark String Specific Methods
/**
* Encrypts a string for social blast service.
*
* @param plainString The string to encrypt;
*
* @return NSString The encrypted string.
*/
- (NSString *)encryptString: (NSString *) plainString{
// Convert string to data and encrypt
NSData *data = [self encryptPBEWithMD5AndDESData:[plainString dataUsingEncoding:NSUTF8StringEncoding] password:@"1111"];
// Get encrypted string from data
return [data base64EncodingWithLineLength:1024];
}
/**
* Descrypts a string from social blast service.
*
* @param plainString The string to decrypt;
*
* @return NSString The decrypted string.
*/
- (NSString *)decryptString: (NSString *) encryptedString{
// decrypt the data
NSData * data = [self decryptPBEWithMD5AndDESData:[NSData dataWithBase64EncodedString:encryptedString] password:@"1111"];
// extract and return string
return [NSString stringWithUTF8String:[data bytes]];
}
#pragma mark -
#pragma mark Crypto Methods
- (NSData *)encryptPBEWithMD5AndDESData:(NSData *)inData password:(NSString *)password {
return [self encodePBEWithMD5AndDESData:inData password:password direction:1];
}
- (NSData *)decryptPBEWithMD5AndDESData:(NSData *)inData password:(NSString *)password {
return [self encodePBEWithMD5AndDESData:inData password:password direction:0];
}
- (NSData *)encodePBEWithMD5AndDESData:(NSData *)inData password:(NSString *)password direction:(int)direction
{
NSLog(@"helper data = %@", inData);
static const char gSalt[] =
{
(unsigned char)0xAA, (unsigned char)0xAA, (unsigned char)0xAA, (unsigned char)0xAA,
(unsigned char)0xAA, (unsigned char)0xAA, (unsigned char)0xAA, (unsigned char)0xAA,
(unsigned char)0x00
};
unsigned char *salt = (unsigned char *)gSalt;
int saltLen = strlen(gSalt);
int iterations = 15;
EVP_CIPHER_CTX cipherCtx;
unsigned char *mResults; // allocated storage of results
int mResultsLen = 0;
const char *cPassword = [password UTF8String];
unsigned char *mData = (unsigned char *)[inData bytes];
int mDataLen = [inData length];
SSLeay_add_all_algorithms();
X509_ALGOR *algorithm = PKCS5_pbe_set(NID_pbeWithMD5AndDES_CBC,
iterations, salt, saltLen);
memset(&cipherCtx, 0, sizeof(cipherCtx));
if (algorithm != NULL)
{
EVP_CIPHER_CTX_init(&(cipherCtx));
if (EVP_PBE_CipherInit(algorithm->algorithm, cPassword, strlen(cPassword),
algorithm->parameter, &(cipherCtx), direction))
{
EVP_CIPHER_CTX_set_padding(&cipherCtx, 1);
int blockSize = EVP_CIPHER_CTX_block_size(&cipherCtx);
int allocLen = mDataLen + blockSize + 1; // plus 1 for null terminator on decrypt
mResults = (unsigned char *)OPENSSL_malloc(allocLen);
unsigned char *in_bytes = mData;
int inLen = mDataLen;
unsigned char *out_bytes = mResults;
int outLen = 0;
int outLenPart1 = 0;
if (EVP_CipherUpdate(&(cipherCtx), out_bytes, &outLenPart1, in_bytes, inLen))
{
out_bytes += outLenPart1;
int outLenPart2 = 0;
if (EVP_CipherFinal(&(cipherCtx), out_bytes, &outLenPart2))
{
outLen += outLenPart1 + outLenPart2;
mResults[outLen] = 0;
mResultsLen = outLen;
}
} else {
unsigned long err = ERR_get_error();
ERR_load_crypto_strings();
ERR_load_ERR_strings();
char errbuff[256];
errbuff[0] = 0;
ERR_error_string_n(err, errbuff, sizeof(errbuff));
NSLog(@"OpenSLL ERROR:\n\tlib:%s\n\tfunction:%s\n\treason:%s\n",
ERR_lib_error_string(err),
ERR_func_error_string(err),
ERR_reason_error_string(err));
ERR_free_strings();
}
NSData *encryptedData = [NSData dataWithBytes:mResults length:mResultsLen]; //(NSData *)encr_buf;
//NSLog(@"encryption result: %@\n", [encryptedData base64EncodingWithLineLength:1024]);
EVP_cleanup();
return encryptedData;
}
}
EVP_cleanup();
return nil;
}
@end
最佳答案
PBEWithMD5AndDES 是指使用 MD5(消息摘要)哈希函数和 DES(数据加密标准)的加密方法,使用 PBKDF2(基于密码的 key 派生函数)等 key 派生函数对某些数据进行加密。
这可以在 iOS 中使用 Swift 使用 Common Crypto 轻松完成。
但这一切都相当陈旧,今天的最佳实践将使用 PBBKDF2 和 SHA 代替 MD5 并使用 AES 代替 DES。 MD5 和 DES 非常弱,不应该在新工作中使用。
如果您不需要与现有的加密文件进行互操作,您可以使用 RNCryptor 。另见 Using RNCryptor Swift
如果您需要互操作,您可以使用 Common Crypto 拼凑出一个匹配方案。如果您需要这样做,请向问题添加更多详细信息,包括示例现有代码和所有输入和输出的十六进制转储以及所有输入参数和您的 Swift 尝试代码。
已弃用文档部分的示例:
基于密码的 key 派生 2 (Swift 3+)
基于密码的 key 派生既可用于从密码文本派生加密 key ,也可用于保存密码以进行身份验证。
可以使用多种哈希算法,包括此示例代码提供的 SHA1、SHA256、SHA512。
rounds 参数用于降低计算速度,这样攻击者就必须在每次尝试上花费大量时间。典型的延迟值在 100 毫秒到 500 毫秒之间,如果性能 Not Acceptable ,可以使用更短的值。
这个例子需要通用加密
必须要有项目的桥接头:
#import <CommonCrypto/CommonCrypto.h>
将 Security.framework
添加到项目中。
参数:
password password String
salt salt Data
keyByteCount number of key bytes to generate
rounds Iteration rounds
returns Derived key
func pbkdf2SHA1(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA1), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}
func pbkdf2SHA256(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}
func pbkdf2SHA512(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
}
func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? {
let passwordData = password.data(using:String.Encoding.utf8)!
var derivedKeyData = Data(repeating:0, count:keyByteCount)
let derivationStatus = derivedKeyData.withUnsafeMutableBytes {derivedKeyBytes in
salt.withUnsafeBytes { saltBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password, passwordData.count,
saltBytes, salt.count,
hash,
UInt32(rounds),
derivedKeyBytes, derivedKeyData.count)
}
}
if (derivationStatus != 0) {
print("Error: \(derivationStatus)")
return nil;
}
return derivedKeyData
}
示例用法:
let password = "password"
//let salt = "saltData".data(using: String.Encoding.utf8)!
let salt = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61])
let keyByteCount = 16
let rounds = 100000
let derivedKey = pbkdf2SHA1(password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds)
print("derivedKey (SHA1): \(derivedKey! as NSData)")
示例输出:
derivedKey (SHA1): <6b9d4fa3 0385d128 f6d196ee 3f1d6dbf>
CBC 模式下使用随机 IV 的 AES 加密 (Swift 3+)
iv是加密数据的前缀
aesCBC128Encrypt
将创建一个随机 IV 并作为加密代码的前缀。
aesCBC128Decrypt
将在解密期间使用带前缀的 IV。
输入是数据,键是数据对象。如果需要在调用方法中转换为和/或自 Base64 等编码形式。
key 的长度应恰好为 128 位(16 字节)、192 位(24 字节)或 256 位(32 字节)。如果使用其他 key 大小,则会抛出错误。
PKCS#7 padding 是默认设置的。
这个例子需要通用加密
必须要有项目的桥接头:
#import <CommonCrypto/CommonCrypto.h>
将 Security.framework
添加到项目中。
这是示例,不是生产代码。
enum AESError: Error {
case KeyError((String, Int))
case IVError((String, Int))
case CryptorError((String, Int))
}
// The iv is prefixed to the encrypted data
func aesCBCEncrypt(data:Data, keyData:Data) throws -> Data {
let keyLength = keyData.count
let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
if (validKeyLengths.contains(keyLength) == false) {
throw AESError.KeyError(("Invalid key length", keyLength))
}
let ivSize = kCCBlockSizeAES128;
let cryptLength = size_t(ivSize + data.count + kCCBlockSizeAES128)
var cryptData = Data(count:cryptLength)
let status = cryptData.withUnsafeMutableBytes {ivBytes in
SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivBytes)
}
if (status != 0) {
throw AESError.IVError(("IV generation failed", Int(status)))
}
var numBytesEncrypted :size_t = 0
let options = CCOptions(kCCOptionPKCS7Padding)
let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCEncrypt),
CCAlgorithm(kCCAlgorithmAES),
options,
keyBytes, keyLength,
cryptBytes,
dataBytes, data.count,
cryptBytes+kCCBlockSizeAES128, cryptLength,
&numBytesEncrypted)
}
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.count = numBytesEncrypted + ivSize
}
else {
throw AESError.CryptorError(("Encryption failed", Int(cryptStatus)))
}
return cryptData;
}
// The iv is prefixed to the encrypted data
func aesCBCDecrypt(data:Data, keyData:Data) throws -> Data? {
let keyLength = keyData.count
let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256]
if (validKeyLengths.contains(keyLength) == false) {
throw AESError.KeyError(("Invalid key length", keyLength))
}
let ivSize = kCCBlockSizeAES128;
let clearLength = size_t(data.count - ivSize)
var clearData = Data(count:clearLength)
var numBytesDecrypted :size_t = 0
let options = CCOptions(kCCOptionPKCS7Padding)
let cryptStatus = clearData.withUnsafeMutableBytes {cryptBytes in
data.withUnsafeBytes {dataBytes in
keyData.withUnsafeBytes {keyBytes in
CCCrypt(CCOperation(kCCDecrypt),
CCAlgorithm(kCCAlgorithmAES128),
options,
keyBytes, keyLength,
dataBytes,
dataBytes+kCCBlockSizeAES128, clearLength,
cryptBytes, clearLength,
&numBytesDecrypted)
}
}
}
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
clearData.count = numBytesDecrypted
}
else {
throw AESError.CryptorError(("Decryption failed", Int(cryptStatus)))
}
return clearData;
}
示例用法:
let clearData = "clearData0123456".data(using:String.Encoding.utf8)!
let keyData = "keyData890123456".data(using:String.Encoding.utf8)!
print("clearData: \(clearData as NSData)")
print("keyData: \(keyData as NSData)")
var cryptData :Data?
do {
cryptData = try aesCBCEncrypt(data:clearData, keyData:keyData)
print("cryptData: \(cryptData! as NSData)")
}
catch (let status) {
print("Error aesCBCEncrypt: \(status)")
}
let decryptData :Data?
do {
let decryptData = try aesCBCDecrypt(data:cryptData!, keyData:keyData)
print("decryptData: \(decryptData! as NSData)")
}
catch (let status) {
print("Error aesCBCDecrypt: \(status)")
}
示例输出:
clearData: <636c6561 72446174 61303132 33343536>
keyData: <6b657944 61746138 39303132 33343536>
cryptData: <92c57393 f454d959 5a4d158f 6e1cd3e7 77986ee9 b2970f49 2bafcf1a 8ee9d51a bde49c31 d7780256 71837a61 60fa4be0>
decryptData: <636c6561 72446174 61303132 33343536>
注意事项:
CBC 模式示例代码的一个典型问题是它将随机 IV 的创建和共享留给了用户。此示例包括 IV 的生成、为加密数据添加前缀并在解密期间使用带前缀的 IV。这将临时用户从 CBC mode 所需的详细信息中解放出来。
为了安全起见,加密的数据也应该有身份验证,这个示例代码没有提供,为了体积小并允许与其他平台更好的互操作性。
还缺少从密码中导出 key 的 key ,建议使用 PBKDF2 将文本密码用作 key Material 。
对于健壮的生产就绪的多平台加密代码,请参阅 RNCryptor。
关于ios - Swift 3 中的 PBEWithMD5AndDES 加密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33429882/