使用CCKeyDerivationPBKDF获取派生密钥

时间:2017-06-26 15:09:14

标签: .net swift aes pbkdf2

使用CCKeyDerivationPBKDF获取伪随机生成的派生密钥时遇到问题。

以下是@zaph使用的代码:

//    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:CCPseudoRandomAlgorithm(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
}

我的问题是它一直为每次调用生成相同的派生密钥。 我正在尝试使用Rfc2898DeriveBytes解密在.Net端加密的数据:

var saltBytes = Encoding.ASCII.GetBytes(salt);
var key = new Rfc2898DeriveBytes(Inputkey, saltBytes);

var aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);   // default keySize 256
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);  // default blockSize 128

在.Net方面,Rfc2898DeriveBytes返回新的随机字节集,但我的Swift代码只为每个调用生成相同的序列。 在Swift方面生成序列有什么问题?

Edit1:当我在Swift中使用来自.net的Rfc2898DeriveBytes生成的Key和IV的字节序列试图解密.net中加密的数据时,它运行正常。

Edit2:好的,我发现Rfc2898DeriveBytes第一次使用GetBytes方法与Swift PBKDF2结果的结果相同。第二次调用GetBytes给出了完全不同的结果。这是为什么?如果我能为此解决问题,那么我的解密应该有效。

aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);   // (1) - the same result as in Swift implementation
aesAlg.IV = key.GetBytes(aesAlg.BlockSize / 8);  // (2) - completly different result

我是否错误地在Swift中初始化IV?

1 个答案:

答案 0 :(得分:0)

.NET实现实际上是一个流。要获得Apple版本的等效答案,您应该在一次通话中询问所需的总字节数,然后将其拆分为您需要的任何部分。