2017-06-26 2 views
0

J'ai un problème avec l'obtention d'une clé dérivée générée pseudo-aléatoire en utilisant CCKeyDerivationPBKDF.Obtention d'une clé dérivée avec CCKeyDerivationPBKDF

Voici le code que je utilise par @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 
} 

Mon problème est qu'il continue de générer les mêmes clés dérivées pour chaque appel. Je suis en train de décrypter les données cryptées sur le côté .Net avec le Rfc2898DeriveBytes:

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 

Du côté .Net, le Rfc2898DeriveBytes rendement nouvel ensemble aléatoire d'octets, mais mon code Swift est la génération que pour chaque appelez la même séquence. Quel est le problème avec cette génération de séquence sur Swift? Edit1: Lorsque j'ai utilisé les séquences d'octets de Key et IV générées par Rfc2898DeriveBytes à partir de .net dans Swift en essayant de décrypter les données cryptées en .net, alors cela fonctionne très bien.

Edit2: Ok, j'ai découvert que la première fois que le Rfc2898DeriveBytes fonctionne avec la méthode GetBytes est le même résultat que sur le résultat Swift PBKDF2. Le deuxième appel GetBytes donne un résultat complètement différent. Pourquoi donc? Si je vais trouver une solution pour cela, mon décryptage devrait fonctionner. Est-ce que j'initialise la IV dans Swift à tort?

+1

Vous devez utiliser un sel différent à chaque production. La même IV doit être utilisée dans le cryptage et le décryptage, une méthode commune pour accomplir ceci est de préfixer les données cryptées avec le IV, il n'a pas besoin d'être secret. Dans le cas de aesAlg.IV, la fonction a été initialisée une fois et deux appels ont été effectués. C'est un problème de sécurité d'utiliser le même IV avec la même clé plus d'une fois. – zaph

+0

@zaph Merci beaucoup pour votre réponse. Excusez-moi, je ne comprends toujours pas. La IV est-elle toujours de longueur 16 octets pour AES256? Voulez-vous dire, que la méthode GetBytes ne devrait pas être appelée deux fois sur la même instance? Je peux poser des questions stupides parce que je suis nouveau dans ce sujet. – PiotrCh

+1

L'AES IV est toujours de 16 octets. Il doit être différent pour chaque utilisation de la même clé de chiffrement. Il est préférable de passer pour le décryptage dans le cadre des données cryptées, souvent pré-pendu aux données cryptées. Peu importe ce que l'IV est tant qu'il est aléatoire. Si une méthode est utilisée qui génère le même IV pour la même clé qui n'est pas sécurisée. – zaph

Répondre

0

L'implémentation .NET est effectivement un flux. Pour obtenir une réponse équivalente à partir de la version d'Apple, vous devez demander le nombre total d'octets dont vous avez besoin en un seul appel, puis le fractionner en toutes les pièces dont vous avez besoin.

+0

Merci pour votre réponse, je vais vérifier cela. – PiotrCh