在swift中使用TripleDes和MD5 [英] using TripleDes and MD5 in swift

查看:108
本文介绍了在swift中使用TripleDes和MD5的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在java代码中有一个使用tripleDes和MD5的算法。有我的java代码:

I have an algorithm in java code for using tripleDes and MD5. there is my java code :

 private String _encrypt(String message, String secretKey) throws Exception {

        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digestOfPassword = md.digest(secretKey.getBytes("utf-8"));
        byte[] keyBytes = Arrays.copyOf(digestOfPassword, 16);

        SecretKey key = new SecretKeySpec(keyBytes, "DESede/ECB/PKCS7Padding");
        Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS7Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] plainTextBytes = message.getBytes("utf-8");


        byte[] buf = cipher.doFinal(plainTextBytes);
        byte [] base64Bytes = Base64.encodeBase64(buf);
        String base64EncryptedString = new String(base64Bytes);

        return base64EncryptedString;
    }

我想在swift中使用tripleDes和MD5,我转换这个java swift的代码但swift中存在一个问题,因为在java中使用16字节而swift使用24字节。如何解决java和swift编码之间的这种差异?
有我的快速代码:

i want to using tripleDes and MD5 in swift, i'm convert this java code to swift but there is an problem in swift because in java using 16 byte and swift using 24 byte. how can solve this difference between coding in java and swift? there is my swift code :

    func myEncrypt(encryptData:String) -> String?{

            let myKeyData : NSData = ("Fanava@Wrapper!1395" as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData
            let myRawData : NSData = encryptData.data(using: String.Encoding.utf8)! as NSData


   let mykeydatamd5 = Data(bytes: myKeyData.bytes, count: 24) // this key convert to 24 bytes but does not hash to md5 

  let mykeydatamd5 = Data(bytes: myKeyData.md5().bytes, count: 24) // this line converted key to md5(), 24byte, but it 


            let buffer_size : size_t = myRawData.length + kCCBlockSize3DES
            let buffer = UnsafeMutablePointer<NSData>.allocate(capacity: buffer_size)
            var num_bytes_encrypted : size_t = 0

            let operation: CCOperation = UInt32(kCCEncrypt)
            let algoritm:  CCAlgorithm = UInt32(kCCAlgorithm3DES)
            let options:   CCOptions   = UInt32(kCCOptionECBMode | kCCOptionPKCS7Padding)
            let keyLength        = size_t(kCCKeySize3DES)

            let Crypto_status: CCCryptorStatus =  CCCrypt(operation, algoritm, options, mykeydatamd5.bytes  , keyLength, nil, myRawData.bytes, myRawData.count, buffer, buffer_size, &num_bytes_encrypted)

            if UInt32(Crypto_status) == UInt32(kCCSuccess){

                let myResult: NSData = NSData(bytes: buffer, length: num_bytes_encrypted)

                free(buffer)

                return myResult.base64EncodedString(options: [])
            }else{
                free(buffer)

                return nil
            }
        }


推荐答案

以下是可以轻松修改TrippleDES的示例代码:

Here is example code which can be easily modified for TrippleDES:

来自子集化的SO文档部分

From the subsetted SO Documentation section

对于CBC模式下的AES加密,使用随机IV(Swift 3 +)

iv以加密数据为前缀

The iv is prefixed to the encrypted data

aesCBC128Encrypt 将创建一个随机IV,并以加密代码为前缀。

aesCBC128Decrypt 将在解密期间使用前缀IV。

aesCBC128Encrypt will create a random IV and prefixed to the encrypted code.
aesCBC128Decrypt will use the prefixed IV during decryption.

输入是数据,键是数据对象。如果需要转换为和/或来自调用方法的编码形式,如Base64。

Inputs are the data and key are Data objects. If an encoded form such as Base64 if required convert to and/or from in the calling method.

密钥应该是128位(16字节),192 -bits(24字节)或256位(32字节)的长度。如果使用其他密钥大小,则会抛出错误。

The key should be exactly 128-bits (16-bytes), 192-bits (24-bytes) or 256-bits (32-bytes) in length. If another key size is used an error will be thrown.

PKCS#7填充默认设置。

此示例需要Common Crypto

它是必须有一个桥接标题到项目:

#import< CommonCrypto / CommonCrypto.h>

添加<项目的code> Security.framework 。

This example requires Common Crypto
It is necessary to have a bridging header to the project:
#import <CommonCrypto/CommonCrypto.h>
Add the Security.framework to the project.

这是示例,而不是生产代码。

This is example, not production code.

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模式所需的详细信息。

Notes:
One typical problem with CBC mode example code is that it leaves the creation and sharing of the random IV to the user. This example includes generation of the IV, prefixed the encrypted data and uses the prefixed IV during decryption. This frees the casual user from the details that are necessary for CBC mode.

为了安全起见,加密数据也应该具有身份验证,这个示例代码不会提供这样的代码,因为它很小并且可以为其他平台提供更好的互操作性。

For security the encrypted data also should have authentication, this example code does not provide that in order to be small and allow better interoperability for other platforms.

还缺少从密码中密钥派生密钥,建议 PBKDF2 是文本密码用作密钥材料。

Also missing is key derivation of the key from a password, it is suggested that PBKDF2 be used is text passwords are used as keying material.

对于强大的生产就绪的多平台加密代码,请参阅 RNCryptor

For robust production ready multi-platform encryption code see RNCryptor.

如果必须为3DES修改此功能。

If you must this functiion can be modified for 3DES.

对于PBKDF2加密**基于密码的密钥派生2(Swift 3 +)

霸基于ssword的密钥派生既可用于从密码文本中导出加密密钥,也可用于保存密码以进行身份​​验证。

Password Based Key Derivation can be used both for deriving an encryption key from password text and saving a password for authentication purposes.

可以使用多种哈希算法,包括SHA1 ,SHA256,SHA512由此示例代码提供。

There are several hash algorithms that can be used including SHA1, SHA256, SHA512 which are provided by this example code.

rounds参数用于使计算变慢,以便攻击者必须在每次尝试上花费大量时间。典型的延迟值在100ms到500ms之间,如果有不可接受的性能,可以使用更短的值。

The rounds parameter is used to make the calculation slow so that an attacker will have to spend substantial time on each attempt. Typical delay values fall in the 100ms to 500ms, shorter values can be used if there is unacceptable performance.

此示例需要Common Crypto

必须为项目设置桥接头:

#import< CommonCrypto / CommonCrypto.h>

Security.framework 添加到项目中。

This example requires Common Crypto
It is necessary to have a bridging header to the project:
#import <CommonCrypto/CommonCrypto.h>
Add the Security.framework to the project.

参数:

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>

这篇关于在swift中使用TripleDes和MD5的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆