Skip to content

Instantly share code, notes, and snippets.

@mqu
Last active March 2, 2022 16:29
Show Gist options
  • Save mqu/86b0671b4ac4c2dba54ae0f7a11e89bc to your computer and use it in GitHub Desktop.
Save mqu/86b0671b4ac4c2dba54ae0f7a11e89bc to your computer and use it in GitHub Desktop.
déchiffrement des fichiers envoyés par ENEDIS/pro chiffrés en AES/CBC-256

tags: ENEDIS, ENEDIS-pro, AES/CBC-265, java

/*
* auteur : Marc Quinton, mai 2021
* src: https://gist.github.com/mqu/86b0671b4ac4c2dba54ae0f7a11e89bc
*
* le décodeur dépend de libcommons-codec-java qui peut être installé de cette facon sur PF Debian/Ubuntu
* apt install libcommons-codec-java
* - classpath: /usr/share/java/commons-codec-1.14.jar
*
* compilation
* export CLASSPATH='/usr/share/java/commons-codec.jar:.'
* javac enedis-decrypt.java
*
* execution :
* - l'application possède 3 arguments :
* - la clé de déchiffrement, sur 64 caractères hexa
* - le fichier source et destination (in, out)
* - la variable CLASSPATH doit être positionnée
*
* java EnedisDecrypt key in-file out-file
*
* FIXME:
* - la variable (const) AES256EncryptionUtilDyn.BLOCK_SIZE n'est pas trouvée ; valeur supposée: 16
* cette constante doit correspondre à l'IV qui est présumé de 16 dans la doc ENEDIS
*
* liens:
* - https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#CBC
* - https://fr.wikipedia.org/wiki/Vecteur_d%27initialisation
* - https://www.enedis.fr/sites/default/files/Enedis-NOI-CF_107E.pdf
*/
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.SecureRandom;
import javax.crypto.spec.*;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.*;
class EnedisDecrypt {
/**
* source ENEDIS / pro
* @param encryptedStream = Fichier chiffré
* @param clearStream = Fichier déchiffré
* @param keyString = Clé AES256 encodée en Hexadécimal (64 caractères)
* @throws Exception
*/
public static void decryptStream(
final InputStream encryptedStream,
final OutputStream clearStream,
final String keyString
) throws Exception {
try {
final byte[] keyBytes = Hex.decodeHex(keyString.toCharArray());
final byte[] key = new byte[keyBytes.length];
System.arraycopy(keyBytes, 0, key, 0, keyBytes.length);
final SecretKey keyValue = new SecretKeySpec(key, "AES");
final Cipher decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding", "SunJCE");
// Lecture de l’IV depuis le 1er bloc du fichier d’entrée - 16 octets
// byte[] iv = new byte[AES256EncryptionUtilDyn.BLOCK_SIZE];
byte[] iv = new byte[16];
encryptedStream.read(iv, 0, iv.length);
IvParameterSpec ivspec = new IvParameterSpec(iv);
decryptCipher.init(Cipher.DECRYPT_MODE, keyValue, ivspec);
final byte[] buffer = new byte[1024];
int noBytes = 0;
final byte[] cipherBlock = new byte[decryptCipher.getOutputSize(buffer.length)];
while ((noBytes = encryptedStream.read(buffer)) != -1) {
final int cipherBytes = decryptCipher.update(buffer, 0, noBytes, cipherBlock);
clearStream.write(cipherBlock, 0, cipherBytes);
}
} catch (final Exception e) {
throw new Exception("Erreur lors du déchiffrement des données", e);
} finally {
try {
if (encryptedStream != null) {
encryptedStream.close();
}
if (clearStream != null) {
clearStream.flush();
clearStream.close();
}
} catch (final IOException localIOException) {}
}
}
/**
* @param key = clé d'encodage 64 caractères hexa fournie par ENEDIS
* @param inputFile = fichier source encodé
* @param outputFile = fichier décodé
* inputfile et outputFile sont optionnels ; dans ce cas, on lit sur stdin et on ecrit sur stdout.
*/
public static void main(String[] args) {
try {
String key = new String(args[0]);
if(args.length==1) {
decryptStream(System.in, System.out, key);
} else {
InputStream fin = new FileInputStream(args[1]);
OutputStream fout = new FileOutputStream(args[2]);
decryptStream(fin, fout, key);
}
} catch (Exception e) {
System.err.println("ENEDIS decrypt error");
e.printStackTrace();
}
}
}
#!/bin/bash
# ENEDIS Enterprise decrypt wrapper
# - ce logicel permet de convertir des données envoyées par ENEDIS Entreprise à ses clients par email
# - le fichier est encodé avec le chiffrement AES/CBC-256
# - il contient une entête de 265 bits (16 octets) suivi des données
# - ce premier bloc est communément appelé IV (Initialisation Vector) :
#
# auteur : Marc Quinton, mai 2021
# src: https://gist.github.com/mqu/86b0671b4ac4c2dba54ae0f7a11e89bc
#
# input format : fichier AES/CBC-265 + clé de 64 caractères Hexa.
# output file : ZIP 2.0 format / 7zip compatible.
# args : key in-file out-file
#
# fonctionnement :
# - vérification des dépendances techniques (uniquement sur PF Linux Debian, Ubuntu)
# - compilation dès que nécessaire
# - execution de l'application java encapsulée dans ce wrapper bash
# - 2 modes de fonctionnement
# - conversion via 2 fichiers : couple (in,out),
# - conversion via les flux (stdin,stdout) (pipes Unix).
# - le fichier reçu, pour ce que j'en connais est une archive ZIP 2.0 que l'on peut extraire avec 7zip
# # apt install p7zip-full
# 7z l enedis-data.zip
# liens:
# - https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#CBC
# - https://fr.wikipedia.org/wiki/Vecteur_d%27initialisation
# - https://www.enedis.fr/sites/default/files/Enedis-NOI-CF_107E.pdf
export CLASS=EnedisDecrypt
export SRC=enedis-decrypt.java
export PKG=libcommons-codec-java
export JAR=/usr/share/java/commons-codec.jar
export CLASSPATH="${JAR}:."
dir=$(dirname $(realpath $0))
cd $dir
_log() {
# echo to stderr
>&2 echo $*
}
_compile() {
[ ! -f $JAR ] && (
_log "le paquet Java suivant devrait être installé : $PKG (apt install $PKG)" ; exit 1
)
# on compile le source java si le fichier .class n'est pas présent
[ ! -f ${CLASS}.class ] && (
_log "compilation de ${CLASS} from $SRC"
javac $SRC
)
[ $SRC -nt ${CLASS}.class ] && (
_log "compilation de ${CLASS} from $SRC"
javac $SRC
)
}
_compile || exit 1
key=$1
case $# in
3)
in=$(realpath $2)
out=$(realpath $3)
java $CLASS $key $in $out
;;
1)
# read from stdin and write to stdout
java $CLASS $key
;;
esac
@mqu
Copy link
Author

mqu commented Nov 30, 2021

vous pouvez laisser un commentaire ici, ou faire un fork du projet. Cordialement, Marc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment