Cet article est l'article du 18e jour du calendrier de l'avent Java 2016. La veille, c'était le "Une histoire sur la décompilation des fichiers JAR" de fullmetal248. Demain, c'est "Birthday frame!"
Le cryptage est le processus de conversion des données d'origine (comme une chaîne de caractères) en quelque chose que vous ne comprenez pas à première vue. Vous pouvez utiliser la clé de déchiffrement pour restaurer la chaîne d'origine, appelée déchiffrement. Le langage Java a une bibliothèque de traitement cryptographique dans le package javax.crypto, il est donc possible d'effectuer un traitement cryptographique à l'aide de diverses méthodes de cryptage.
Ci-dessous, nous expliquerons les chiffrements AES qui sont souvent utilisés dans le traitement cryptographique. De plus, puisque j'ai créé une classe de bibliothèque pour utiliser le cryptage AES dans un programme, je vais expliquer le code source et comment l'utiliser.
Commençons par une connaissance de base du cryptage AES.
Dans la seconde moitié des années 90, il est devenu clair que le code DES utilisé par le gouvernement américain à des fins publiques serait cassé par certains ordinateurs personnels (peut-être en utilisant environ 30). Par conséquent, nous avons décidé d'organiser un concours mondial et de solliciter de nouvelles méthodes de cryptage. Il y avait des entrées telles que le code elliptique du Japon, mais le code AES a finalement été adopté.
Le cryptage AES coupe le tout en petits blocs et effectue le traitement de cryptage petit à petit. À ce moment-là, le mode CBC consiste à prendre le XOR du bloc qui a été chiffré immédiatement avant et le bloc qui doit être chiffré ensuite, puis à le chiffrer. Étant donné que le cryptage du bloc précédent affecte le cryptage du bloc suivant, il a l'excellente fonctionnalité qu'il n'est pas possible de deviner quel type de cryptage une chaîne de caractères spécifique sera encodée en comparant le texte brut et le cryptage. Il y a.
IV(Initial Vector)
En mode CBC, le premier bloc n'a pas de blocs de données superposés XOR. Par conséquent, pour le premier bloc, une valeur est créée artificiellement, mais il s'agit de IV. IV est une chaîne de 128 bits lors de l'utilisation de classes Java standard.
Si vous donnez un IV différent à chaque fois pendant le processus de cryptage, vous pouvez avoir le même texte brut mais un cryptage différent à chaque fois. Donc IV utilise une chaîne aléatoire. Utilisez RandomStringUtils dans Commons Library (commons-lang3-3.4-bin.zip) pour obtenir des chaînes aléatoires , Vous pouvez facilement générer en spécifiant la longueur et le type de caractères à utiliser.
Chaîne de clé utilisée à la fois pour le chiffrement et le déchiffrement. Cela devrait également être de 128 bits, soit exactement 16 caractères. Vous pouvez créer librement le contenu, mais si la clé de déchiffrement est trop longue, elle sera tronquée, et si elle est trop courte, la chaîne de caractères sera complétée.
Voici une classe de bibliothèque qui crypte et décrypte. Pour faire le cryptage, créez simplement une instance de la classe Crypt et utilisez la méthode encrypto ou decrypto. Cependant, comme il est nécessaire de sauvegarder la clé et l'IV lors de son utilisation, un échantillon d'utilisation spécifique sera publié ultérieurement.
Tout d'abord, nous avons besoin d'une classe commons, voici donc le fichier pom.xml correspondant. J'ai écrit la signification et l'utilisation de pom dans Posté le 13, alors jetez un œil là-bas.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>crypto</groupId>
<artifactId>crypto</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.5</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Vient ensuite la classe Crypto pour le traitement cryptographique. Le projet est créé dans Eclipse après avoir créé un projet Java normal, en cliquant avec le bouton droit sur le projet et en sélectionnant [Configuration] ⇒ [Convertir en projet maven].
package com.tkxwebs.crypto;
import java.io.Serializable;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
/**
*Cryptage AES/Classe de cryptage en mode CBC
* @auteur Takashi Kawaba [email protected]
*/
public class Crypto implements Serializable {
private Cipher encrypter; //Crypto-monnaie pour le cryptage
private Cipher decrypter; //Dispositif de cryptage pour le décryptage
/*Constructeur (les arguments sont la clé de déchiffrement et IV)
*Les deux arguments vont de la chaîne à l'octet[]Spécifiez ce qui a été converti en
*/
public Crypto(byte[] secretKey, byte[] ivs) throws Exception{
IvParameterSpec iv = new IvParameterSpec(ivs); //Créer une valeur initiale pour le bloc de démarrage au moment du chiffrement
SecretKeySpec key = new SecretKeySpec(secretKey, "AES"); //Créer un ensemble de méthode de cryptage + clé de décryptage
encrypter = Cipher.getInstance("AES/CBC/PKCS5Padding"); //Créez un périphérique de cryptage en spécifiant la méthode de cryptage et la méthode de génération
encrypter.init(Cipher.ENCRYPT_MODE, key, iv); //Réglez le périphérique de cryptage en mode de cryptage
decrypter = Cipher.getInstance("AES/CBC/PKCS5Padding"); //Créer un autre périphérique de chiffrement
decrypter.init(Cipher.DECRYPT_MODE, key, iv); //Réglez le périphérique de chiffrement en mode de déchiffrement
}
/*Méthode pour effectuer le processus de cryptage*/
public String encrypto(String text) throws Exception {
byte[] crypto = encrypter.doFinal(text.getBytes()); //Crypter
byte[] str64 = Base64.getEncoder().encode(crypto); //Convertir en un tableau de caractères pour l'affichage
return new String(str64); //Faites-en une chaîne de caractères
}
/*Méthode pour effectuer le processus de décryptage*/
public String decrypto(String str64) throws Exception {
byte[] str = Base64.getDecoder().decode(str64); //Convertir la chaîne de chiffrement en binaire d'origine
byte[] text = decrypter.doFinal(str); //Décrypter
return new String(text); //Convertir en chaîne et retourner
}
}
La classe FileUtil suivante est un utilitaire utilisé pour stocker la clé de chiffrement et IV.
package com.tkxwebs.crypto;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class FileUtil {
public static void writeBytes(byte[] b, String path) {
try(ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(path))) {
o.write(b);
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] readBytes(String path) {
byte[] b = new byte[16];
try(ObjectInputStream in = new ObjectInputStream(new FileInputStream(path))) {
in.read(b, 0, 16);
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
}
Voyons comment l'utiliser réellement.
Quand utilisez-vous la cryptographie? Il crypte les mots de passe, etc. Ensuite, il est déchiffré lors de l'assemblage, par exemple, lors du processus de connexion. De toute évidence, le cryptage et le décryptage sont exécutés à des moments différents.
Par conséquent, la clé de déchiffrement et l'IV doivent être enregistrés (et chiffrés davantage) dans un fichier ou une base de données du système pour le stockage. Ici, le processus de cryptage supplémentaire est omis, mais dans tous les cas, la clé de décryptage et la clé de décryptage doivent être écrites ou lues au moment du cryptage et du décryptage.
Dans cet exemple d'utilisation, un utilitaire (classe FileUtil) qui enregistre le tableau d'octets en tant qu'objet dans un fichier est utilisé pour la lecture et l'écriture.
package sample;
import org.apache.commons.lang3.RandomStringUtils;
import com.tkxwebs.crypto.Crypto;
import com.tkxwebs.crypto.FileUtil;
public class CryptoExample {
public static void main(String args[]) {
/*******************************************************************************
*Étant donné que le cryptage et le décryptage sont généralement effectués séparément, la clé de décryptage et IV sont des fichiers.
*Enregistrer et charger au moment de l'exécution pour l'utiliser
*******************************************************************************/
/*------------------------------------------------------------------------------
Préparation des données
--------------------------------------------------------------------------------*/
byte[] iv = RandomStringUtils.randomAlphanumeric(16).getBytes();// IV(Valeur initiale 128 bits de longueur fixe pour le bloc de départ au moment du cryptage)
byte[] key = "kawaba_2015_key_".getBytes(); //Clé de déchiffrement(128 bits de longueur fixe)
/*------------------------------------------------------------------------------
Enregistrer IV et la clé de déchiffrement dans le fichier
--------------------------------------------------------------------------------*/
FileUtil.writeBytes(iv, "iv");
FileUtil.writeBytes(key, "secret");
/*------------------------------------------------------------------------------
Affichage des données
--------------------------------------------------------------------------------*/
System.out.println("IV(Valeur initiale pour le bloc de démarrage)="+new String(iv)+ "("+iv.length + "byte)");
System.out.println("Clé de déchiffrement =" + new String(key) + "(16byte)");
/*------------------------------------------------------------------------------
Traitement du cryptage
--------------------------------------------------------------------------------*/
String source = "Que devrais-je faire"; //Chaîne de caractères à chiffrer
String result = ""; //Chaîne de résultat chiffrée
try { //Créer un objet Crypto
Crypto c = new Crypto(FileUtil.readBytes("secret"), FileUtil.readBytes("iv")); //Lire la clé de déchiffrement et IV à partir du fichier
result = c.encrypto(source); //Obtenez la chaîne cryptée
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Code =" + result); //Afficher la chaîne cryptée
/*------------------------------------------------------------------------------
Processus de décryptage
--------------------------------------------------------------------------------*/
try { //Créer un objet Crypto
Crypto c2 =new Crypto(FileUtil.readBytes("secret"), FileUtil.readBytes("iv")); //Lire la clé de déchiffrement et IV à partir du fichier
result = c2.decrypto(result); //Obtenez la chaîne déchiffrée
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Décryptage =" + result); //Afficher la chaîne d'origine
}
}
Lorsque j'exécute ce code, j'obtiens ce qui suit: Essayez-le plusieurs fois et assurez-vous que la même chaîne est convertie en un chiffre différent à chaque fois.
IV(Valeur initiale pour le bloc de démarrage)=u7aTAfOMMKJvD02S(16byte)
Clé de déchiffrement = kawaba_2015_key_(16byte)
Code = piiKP/GX3HcykHbXAHjptPDtEORdx6oASa2luFtAbZA=
Décryptage = Et si