tags: ENEDIS, ENEDIS-pro, AES/CBC-265, java
Last active
March 2, 2022 16:29
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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(); | |
} | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
vous pouvez laisser un commentaire ici, ou faire un fork du projet. Cordialement, Marc.