4 votes

Comment puis-je crypter une chaîne en Java pour qu'elle soit exactement cryptée de la même manière qu'en ColdFusion?

J'ai des données chiffrées en ColdFusion que je dois pouvoir déchiffrer et chiffrer avec exactement la même valeur en utilisant Java. J'espérais que quelqu'un pourrait m'aider avec ceci. Je vais spécifier tout ce qui est utilisé en ColdFusion, sauf le PasswordKey réel, que je dois garder secret à des fins de sécurité. Le PasswordKey fait 23 caractères de long. Il utilise des lettres majuscules et minuscules, des chiffres, ainsi que les signes + et =. Je sais que cela fait beaucoup de demande, mais toute aide serait grandement appréciée.

J'ai essayé d'utiliser un exemple de chiffrement Java que j'ai trouvé en ligne et de simplement remplacer la ligne ci-dessous avec les 23 caractères utilisés dans notre application CF :

private static final byte[] keyValue = new byte[] {'T', 'h', 'i', 's', 'I', 's', 'A', 'S', 'e', 'c', 'r', 'e', 't', 'K', 'e', 'y' };`

Mais j'obtiens l'erreur :

java.security.InvalidKeyException: Longueur de clé AES non valide : 23 octets

Le code CF est :

Application.PasswordKey = "***********************";
Application.Algorithm = "AES";
Application.Encoding = "hex";

2voto

jtahlborn Points 32515

Votre clé secrète est probablement une clé encodée en Base64 (23 caractères devraient décoder à environ 16 octets, ce qui est la bonne longueur pour une clé de 128 bits pour AES).

Donc, dans votre code Java, exécutez d'abord votre chaîne de clé secrète à travers un décodeur Base64 pour obtenir un byte[] de la longueur appropriée (16 octets) pour l'algorithme AES.

2voto

mtariq Points 1194

128 mais le chiffrement AES prend en charge une taille de clé de 16 octets.
16 * 8 = 128 bits, même dans l'exemple la clé est de 16 octets.

Il semble que votre clé soit en Base64, utilisez Base64.decode(clé ou clé.getBytes()) pour obtenir le tableau d'octets, vérifiez qu'il fait bien 16 octets sinon ajoutez des octets de bourrage pour arriver à 16 octets.

1voto

kei23th Points 283

Merci à tous pour votre aide. Je voulais poster ma solution finale pour que d'autres puissent l'utiliser. Je inclue tout mon code de package de cryptage moins la clé de mot de passe spécifique (encore une fois pour des raisons de sécurité). Ce code crée la même chaîne hexadécimale que le code CF répertorié dans la question, et la déchiffre en chaîne de texte anglais correcte.

J'ai trouvé les fonctions bytesToHex et hexStringToByteArray dans une autre question sur stackoverflow, donc mes remerciements aux utilisateurs maybeWeCouldStealAVan et Dave L. respectivement aussi. Je pense que je vais examiner d'autres encodeurs/décodeurs de base 64 au cas où celui de sun serait un jour rendu indisponible, mais cela fonctionne certainement pour le moment. Merci encore.

package encryptionpackage;

import java.security.*;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.Cipher; 
import javax.crypto.spec.SecretKeySpec;
import sun.misc.*;

public class encryption 
{
    // Remarque : Le paramètre par défaut CF complet est "AES/ECB/PKCS5Padding"
    private static final String ALGORITHM = "AES";
    // La clé de 24 caractères de mon application CF (encodée en base64)
    // généralement générée avec : generateSecretKey("AES") 
    private static final String passKey = "***********************"; 

     public static String encrypt(String valueToEnc) throws Exception 
     {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.ENCRYPT_MODE, key);
        byte[] encValue = c.doFinal(valueToEnc.getBytes());
        String encryptedValue = bytesToHex(encValue);
        return encryptedValue;
    }

    public static String decrypt(String encryptedValue) throws Exception 
    {
        Key key = generateKey();
        Cipher c = Cipher.getInstance(ALGORITHM);
        c.init(Cipher.DECRYPT_MODE, key);
        byte[] decordedValue = hexStringToByteArray(encryptedValue);
        byte[] decValue = c.doFinal(decordedValue);
        String decryptedValue = new String(decValue);
        return decryptedValue;
    }

    private static Key generateKey() throws Exception 
    {
          byte[] keyValue;
          keyValue = new BASE64Decoder().decodeBuffer(passKey);
        Key key = new SecretKeySpec(keyValue, ALGORITHM);

        return key;
    }

    public static String bytesToHex(byte[] bytes) 
    { 
        final char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; 
        char[] hexChars = new char[bytes.length * 2]; 
        int v; 
        for ( int j = 0; j < bytes.length; j++ ) 
        { 
            v = bytes[j] & 0xFF; 
            hexChars[j * 2] = hexArray[v >>> 4]; 
            hexChars[j * 2 + 1] = hexArray[v & 0x0F]; 
        } 
        return new String(hexChars); 
    } 

    public static byte[] hexStringToByteArray(String s) 
    { 
        int len = s.length(); 
        byte[] data = new byte[len / 2]; 
        for (int i = 0; i < len; i += 2) 
        { 
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 
                                 + Character.digit(s.charAt(i+1), 16)); 
        } 
        return data; 
    } 

}

0voto

Lai Xin Chu Points 2432

Le chiffrement AES ne prend en charge qu'une taille de clé de 128 bits, 192 bits ou 256 bits.

http://en.wikipedia.org/wiki/Advanced_Encryption_Standard

Vous ne pouvez pas simplement prendre n'importe quel tableau d'octets et l'utiliser comme clé AES. Dans le code d'exemple que vous voyez ci-dessus, l'exemple utilise cleverement 16 caractères, ce qui correspond à une clé de 128 bits.

Cela est dû au fait qu'1 caractère ou plutôt 1 octet correspond à 8 bits.

Un tableau d'octets de 16 valeurs correspondra alors à 16 * 8 = 128 bits

23 caractères = 23 * 8 = 184 bits, donc c'est une taille de clé invalide.

Vous avez besoin de 16 caractères, 24 caractères ou 32 caractères.

Cela dit, utiliser simplement des caractères pour le chiffrement AES est extrêmement insécuritaire. Utilisez une clé aléatoire appropriée et sécurisée à des fins de chiffrement.

Pour générer une clé AES sécurisée et aléatoire :

SecureRandom random = new SecureRandom();
byte [] secret = new byte[16];
random.nextBytes(secret);

http://docs.oracle.com/javase/6/docs/api/java/security/SecureRandom.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X