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
4 Réponses :
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: p> et le déchiffrement est donc: p> qui peut être implémenté dans Java comme ceci: p> 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. p> 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 p> 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 Il est probablement préférable de spécifier explicitement le digest dans la ligne de commande interface (par exemple
EVP_BYTESKOKEY Commandes> et les commandes telles que
OpenSSL Enc code>. P>
-md md5 code> pour la compatibilité vers l'arrière ou
SHA-256 code> pour la compatibilité des transferts) pour le code Java utilise le même algorithme de Digest (
" MD5 " code> ou
" SHA-256 " code> y compris le tableau de bord). Voir aussi les informations dans cette réponse . p> p>
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" i> - 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" i> - ceci n'est pas non plus possible si vous utilisez la commande Enc code> 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 code> prend en charge
-pbkdf2 code> et sélectionnable utilisateur
--iter n code>
ci-dessous sont 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;
}
}
N'utilisez pas ASE-128-CBC, utilisez ASE-128-BCE.
hashpwd = OPENSSL ENC -AES-128-ECB -SALT -IN -OUT -OUT -K $ HASHPWD P> Le code Java est ici: P > écho -n $ mot de passe | OpenSSL SHA1 | SED 'S #. * = \\ s * ## g' | CUT -C 1-32 CODE> 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);
}
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 CODE> 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é i> que le code OpenSSL, qui est un art en soi; il est déjà loin de la par.
in kotlin: