2010-05-03 4 views
3

J'essaie de créer un programme qui crypte les données en utilisant AES, puis crypte la clé AES avec RSA, puis décrypte. Cependant, une fois que je crypte la clé AES, elle sort à 128 octets. RSA me permettra seulement de décrypter 117 octets ou moins, donc quand je vais déchiffrer la clé AES, il y a une erreur.Clé AES cryptée trop grande pour déchiffrer avec RSA (Java)

Code relavent:

KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); 
    kpg.initialize(1024); 
    KeyPair kpa = kpg.genKeyPair(); 
    pubKey = kpa.getPublic(); 
    privKey = kpa.getPrivate(); 

    updateText("Private Key: " +privKey +"\n\nPublic Key: " +pubKey); 

    updateText("Encrypting " +infile); 
    //Genereate aes key 
    KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
    kgen.init(128); // 192/256 
    SecretKey aeskey = kgen.generateKey(); 
    byte[] raw = aeskey.getEncoded(); 

    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 

    updateText("Encrypting data with AES"); 
    //encrypt data with AES key 
    Cipher aesCipher = Cipher.getInstance("AES"); 
    aesCipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
    SealedObject aesEncryptedData = new SealedObject(infile, aesCipher); 

    updateText("Encrypting AES key with RSA"); 
    //encrypt AES key with RSA 
    Cipher cipher = Cipher.getInstance("RSA"); 
    cipher.init(Cipher.ENCRYPT_MODE, pubKey); 
    byte[] encryptedAesKey = cipher.doFinal(raw); 

    updateText("Decrypting AES key with RSA. Encrypted AES key length: " +encryptedAesKey.length); 
    //decrypt AES key with RSA  
    Cipher decipher = Cipher.getInstance("RSA"); 
    decipher.init(Cipher.DECRYPT_MODE, privKey); 
    byte[] decryptedRaw = decipher.doFinal(encryptedAesKey); //error thrown here because encryptedAesKey is 128 bytes 
    SecretKeySpec decryptedSecKey = new SecretKeySpec(decryptedRaw, "AES"); 

    updateText("Decrypting data with AES"); 
    //decrypt data with AES key 
    Cipher decipherAES = Cipher.getInstance("AES"); 
    decipherAES.init(Cipher.DECRYPT_MODE, decryptedSecKey); 
    String decryptedText = (String) aesEncryptedData.getObject(decipherAES); 

    updateText("Decrypted Text: " +decryptedText); 

Toute idée sur la façon de contourner ce problème?

+0

Votre description de l'erreur n'a pas de sens. Vous devriez publier la trace complète de la pile. En l'état, la partie RSA de votre code devrait fonctionner correctement. Je l'ai testé, et ça fonctionne très bien pour moi. –

+0

Ahh maintenant je vois, vous êtes un bâtard paresseux. Je vois que tu as posté le même code il y a un mois sur les forums du soleil * et * on t'a dit quel était ton bug. Ensuite, vous venez de republier le même code juste pour perdre le temps de tout le monde. Si j'ai couru ce site, je supprimerais votre compte. –

Répondre

1

Modifier: J'ai mal compris le problème. Vous devez utiliser une clé RSA plus grande, par exemple RSA 4096 vous permet de crypter 501 octets.

Vous pouvez essayer d'utiliser AES dans OFB mode qui vous permettra de crypter un message de taille arbitraire. Alternativement, vous pouvez utiliser un chiffrement de flux comme RC4 qui vous permettra également de crypter un message de taille arbitraire. Si vous allez avec RC4 assurez-vous d'utiliser RC4-drop1024 qui signifie simplement que vous jetez les 1024 premiers octets de texte de chiffrement. Les premiers 1024 bits de rc4 sont prévisibles et ceci ainsi que de nombreux autres problèmes ont conduit à la chute de WEP utilisé pour sécuriser le WIFI. Un autre problème avec RC4 est que vous ne pouvez pas réutiliser le flux PRNG. Fondamentalement, vous devez utiliser une clé différente pour chaque message ou un attaquant peut casser le système assez facilement en utilisant rien de plus que XOR. J'irais avec AES en mode OFB, mais RC4 peut être utilisé en toute sécurité.

Tous les autres modes de chiffrement par bloc produisent toujours un message divisible par leur taille de bloc. Par exemple, AES 128 en mode CBC produira toujours un message divisible par 128 bits. Si le message est inférieur à 128 bits, il est souvent rempli de zéros. Si c'est une chaîne, alors elle devrait être terminée et vous ne devez pas vous inquiéter. Sur un côté, assurez-vous de ne pas utiliser ECB mode. Un autre problème est que je ne vois pas que vous utilisez un vecteur d'initialisation (IV) rotatif ou aléatoire, ce qui affaiblit considérablement tout chiffrement par bloc. L'échec à implémenter correctement un IV est une vulnérabilité reconnue par CWE-329.

+0

Merci pour les suggestions, en particulier sur IV, mais le problème n'est pas avec l'implémentation de AES mais plutôt RSA. Chaque fois que je crypte la clé AES de 16 octets (avec RSA), le résultat est de 128 octets, ce qui est plus grand que le cap de 117 octets de RSA, donc je suis incapable de le déchiffrer. –

+0

@Petey B Oah désolé j'ai mal compris, c'est un problème encore plus facile à résoudre, il suffit d'utiliser une plus grande clé RSA. Par exemple RSA 4096 vous permet de crypter 501 octets. – rook

+0

Tout va bien maintenant, merci –

2

Lorsque vous utilisez le cryptage, en spécifiant toujours le remplissage. Sinon, votre texte en clair sera complété à la taille du bloc. Par exemple,

Cipher aes = Cipher.getInstance("AES/CBC/PKCS5Padding"); 

Cipher rsa = Cipher.getInstance("RSA/None/PKCS1Padding"); 

La clé AES n'a que 16 octets pour 128 bits. Donc, il devrait bien s'intégrer dans n'importe quel bloc RSA.

+0

Merci, avez-vous plus d'informations sur les schémas de remplissage pour lesquels les algorithmes sont possibles? –

+0

Le remplissage pris en charge par chaque algorithme dépend de l'implémentation JCE. Les valeurs dans mon exemple sont les paramètres recommandés pour AES et RSA. –

+2

-1 Son problème n'a absolument rien à voir avec le type de rembourrage utilisé. Un chiffrement par blocs produira toujours des blocs de la même taille, et le remplissage est une exigence. Par exemple, AES 128 produira toujours un texte chiffré divisible par 128 bits. Sauf si vous utilisez le mode OFB. – rook

1

Vous pourriez obtenir des problèmes de complexité en utilisant simplement le mode/la fonction de bouclage de la classe Cipher. Vous pouvez voir my source code pour un exemple de la façon de le faire.

Questions connexes