11
votes

Comment déchiffrer le fichier en Java crypté avec OpenSSL Commande en utilisant AES?

J'ai besoin de déchiffrer Java un fichier crypté dans UNIX avec la commande suivante:

openssl aes-256-cbc -d -a -in password.txt.enc -out password.txt.new
mypass


0 commentaires

4 Réponses :


25
votes

OpenSSL utilise généralement sa propre méthode mot de passe en fonction de dérivation de clé, spécifiée dans EVP_BytesToKey < / Code> , veuillez consulter le code ci-dessous. De plus, il code implicitement le ciIphertext comme base 64 sur plusieurs lignes, ce qui serait nécessaire de l'envoyer dans le corps d'un message de messagerie.

Le résultat est donc, dans pseudocode: xxx

et le déchiffrement est donc: xxx

qui peut être implémenté dans Java comme ceci: xxx

Méfiez-vous que le code spécifie ASCII comme jeu de caractères. Le jeu de caractères utilisé peut différer pour votre application / terminal / os.


En général, vous devez forcer OpenSSL à utiliser l'algorithme PBKDF2 approuvé NIST, comme en utilisant la méthode de dérivation de la clé OpenSSL - avec un compte d'itération de 1 - est précaire. Cela peut vous obliger à utiliser une solution différente de OpenSSL. Notez que le cryptage par mot de passe est par nature plutôt précaire - les mots de passe sont beaucoup moins sûres que les clés symétriques générés aléatoirement


Openssl 1.1.0c a changé l'algorithme de Digest utilisé dans certains composants internes. Autrefois, MD5 a été utilisé et 1.1.0 est passé à SHA256. Soyez prudent que le changement ne vous affecte pas dans les deux EVP_BYTESKOKEY et les commandes telles que OpenSSL Enc .

Il est probablement préférable de spécifier explicitement le digest dans la ligne de commande interface (par exemple -md md5 pour la compatibilité vers l'arrière ou SHA-256 pour la compatibilité des transferts) pour le code Java utilise le même algorithme de Digest ( " MD5 " ou " SHA-256 " y compris le tableau de bord). Voir aussi les informations dans cette réponse .


8 commentaires

Ils ne devraient pas différer - c'est l'ensemble des normes telles que PKCS5. Vos conseils sur l'ensemble sont certainement bien cependant


"N'oubliez pas de faire correspondre le codage de caractères ..." Le cryptage doit en effet correspondre, mais le codage peut différer.


Cela a fonctionné pour moi. Et de manière prévisible, j'ai eu des problèmes avec ASCII VS UTF8.


J'ai utilisé cette fonction et cela fonctionne bien pour le cryptage salé et le déchiffrement. Il décrypte également correctement quand il n'y a pas de sel. Cependant, dans le programme que j'ai écrit, il ne semble pas crypté correctement les chaînes non salées. Y a-t-il une mise en garde qui me manque lorsque crypter des cordes non salées?


"L'IV est inutile, OpenSSL pourrait aussi bien utiliser" - hmmm, no. Le IV est dérivé de la combinaison de mot de passe + du sel, ce qui signifie qu'il remplit toujours son objectif tant que le sel est généré aléatoirement (ce qui est, si le même clairtext est crypté avec le même mot de passe, le ciIPhertext résultant est différent). Le hasard est juste créé dans une autre étape (c.-à-d.: Le sel au lieu de la IV)


"En général, vous devez forcer OpenSSL à utiliser l'algorithme PBKDF2 approuvé NIST, bien que" - ceci n'est pas non plus possible si vous utilisez la commande Enc de OpensSL (Sauf si vous spécifiez la clé et IV directement; mais il n'y a aucun moyen de contrôler les utilisations de KDF OpenSSL)


@NullUSeException L'IV est inutile car il n'y a pas besoin d'un IV aléatoire si la clé est toujours différente. Et la clé est unique à cause du sel. Le IV est nécessaire pour faire des paires de clé / iv uniques. Il est donc plutôt inutile de le déranger de la même combinaison de sel / mot de passe.


@ NullUSException + mise à jour: openssl 1.1.1 (2018-09) Enc prend en charge -pbkdf2 et sélectionnable utilisateur --iter n



7
votes

ci-dessous sont opensslpbeinputtream strong> et opensslpbeoutputtream strong> qui peut être utilisé pour chiffrer / déchirer des flux arbitraires d'octets de manière compatible avec openssl.

Exemple d'utilisation:

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.PBEParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

class OpenSSLPBECommon {

protected static final int SALT_SIZE_BYTES = 8;
protected static final String OPENSSL_HEADER_STRING = "Salted__";
protected static final String OPENSSL_HEADER_ENCODE = "ASCII";

protected static Cipher initializeCipher(char[] password, byte[] salt, int cipherMode,
                                         final String algorithm, int iterationCount) throws NoSuchAlgorithmException, InvalidKeySpecException,
        InvalidKeyException, NoSuchPaddingException, InvalidAlgorithmParameterException {

    PBEKeySpec keySpec = new PBEKeySpec(password);
    SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
    SecretKey key = factory.generateSecret(keySpec);

    Cipher cipher = Cipher.getInstance(algorithm);
    cipher.init(cipherMode, key, new PBEParameterSpec(salt, iterationCount));

    return cipher;
}

}


0 commentaires

-2
votes

N'utilisez pas ASE-128-CBC, utilisez ASE-128-BCE.

Ne prenez que 16 octets uniquement comme clé car la touche est de 128 bits h1>

la sortie de hachage est imprimée en hexagone, que tous les 2 caractères présentent une valeur d'octet h1>

hashpwd = écho -n $ mot de passe | OpenSSL SHA1 | SED 'S #. * = \\ s * ## g' | CUT -C 1-32 CODE> P>

OPENSSL ENC -AES-128-ECB -SALT -IN -OUT -OUT -K $ HASHPWD P>

Le code Java est ici: P >

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;


    //openssl enc -nosalt -aes-128-ecb
    // -in <input file>
    // -out <output file>
    // -K <16 bytes in hex, for example : "abc" can be hashed in SHA-1, the first 16 bytes in hex is a9993e364706816aba3e25717850c26c>
    private final static String TRANSFORMATION = "AES"; // use aes-128-ecb in openssl

public static byte[] encrypt(String passcode, byte[] data) throws CryptographicException {
        try {
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, genKeySpec(passcode));
            return cipher.doFinal(data);
        } catch (Exception ex) {
            throw new CryptographicException("Error encrypting", ex);
        }
    }


    public static String encryptWithBase64(String passcode, byte[] data) throws CryptographicException {
        return new BASE64Encoder().encode(encrypt(passcode, data));
    }

    public static byte[] decrypt(String passcode, byte[] data) throws CryptographicException {
        try {
            Cipher dcipher = Cipher.getInstance(TRANSFORMATION);
            dcipher.init(Cipher.DECRYPT_MODE, genKeySpec(passcode));
            return dcipher.doFinal(data);
        } catch (Exception e) {
            throw new CryptographicException("Error decrypting", e);
        }
    }


    public static byte[] decryptWithBase64(String passcode, String encrptedStr) throws CryptographicException {
        try {
            return decrypt(passcode, new BASE64Decoder().decodeBuffer(encrptedStr));
        } catch (Exception e) {
            throw new CryptographicException("Error decrypting", e);
        }
    }

    public static SecretKeySpec genKeySpec(String passcode) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        byte[] key = passcode.getBytes("UTF-8");
        MessageDigest sha = MessageDigest.getInstance("SHA-1");
        key = sha.digest(key);
        key = Arrays.copyOf(key, 16); // use only first 128 bit
        return new SecretKeySpec(key, TRANSFORMATION);
    }


2 commentaires

N'utilisez pas le mode ECB, il n'est pas sécurisé, voir Mode ECB , faites défiler jusqu'au pingouin. Utilisez plutôt le mode CBC avec un IV aléatoire, il suffit de préfixer les données cryptées avec le IV pour une utilisation en décryptage, elle n'a pas besoin de ne pas secrète.


Je suis à peu près sûr que la déclaration: N'utilisez pas de classes de mise en œuvre (telles que dans le paquet SUN.MISC dans le didacticiel Java depuis la version 1.0, publié il y a des Eons. Vous avez besoin d'une fonction de hachage de mot de passe. Pour dériver de manière sécurisée une clé d'un mot de passe. À l'aide de la BCE au lieu de CBC et SHA1 au lieu d'Evp_BytestOkety, il en fait Même moins sécurisé que le code OpenSSL, qui est un art en soi; il est déjà loin de la par.



0
votes

in kotlin: xxx


0 commentaires