Nous avons résumé comment gérer les techniques cryptographiques suivantes avec la bibliothèque standard de Java. Nous expliquerons brièvement chaque technologie cryptographique et présenterons un exemple de mise en œuvre.
--Code symétrique (AES)
Les algorithmes utilisés dans les exemples d'implémentation sont répertoriés entre parenthèses.
Le cryptage symétrique est une technologie de protection de la confidentialité des messages. Il présente les caractéristiques suivantes.
Il s'agit d'une méthode pour générer une clé de chiffrement symétrique (clé commune).
public SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
return keyGen.generateKey();
}
Comment générer un vecteur d'initialisation. Le vecteur d'initialisation est une chaîne de bits aléatoire qui est destinée à être utilisée afin que différents chiffrements puissent être obtenus à chaque fois, même s'ils sont chiffrés à l'aide de la même clé.
public IvParameterSpec generateIV() {
SecureRandom random = new SecureRandom();
byte[] iv = new byte[16];
random.nextBytes(iv);
return new IvParameterSpec(iv);
}
Comment crypter le message.
Spécifiez l'algorithme, le mode de bloc et la méthode de remplissage lors de l'acquisition de l'instance Cipher
.
Voir JavaDoc pour la classe Cipher
pour une combinaison d'algorithmes, de modes de bloc et de méthodes de remplissage.
public byte[] encrypto(String plainText, SecretKey key, IvParameterSpec iv) throws GeneralSecurityException {
//Format:"algorithme/Mode bloc/Méthode de remplissage"
Cipher encrypter = Cipher.getInstance("AES/CBC/PKCS5Padding");
encrypter.init(Cipher.ENCRYPT_MODE, key, iv);
return encrypter.doFinal(plainText.getBytes());
}
C'est la méthode de déchiffrement du code. Spécifiez l'algorithme, le mode de blocage et la méthode de remplissage comme vous l'avez fait pour le chiffrement.
public String decrypto(byte[] cryptoText, SecretKey key, IvParameterSpec iv) throws GeneralSecurityException {
//Format:"algorithme/Mode bloc/Méthode de remplissage"
Cipher decrypter = Cipher.getInstance("AES/CBC/PKCS5Padding");
decrypter.init(Cipher.DECRYPT_MODE, key, iv);
return new String(decrypter.doFinal(cryptoText));
}
Le cryptage à clé publique est une technologie permettant de protéger la confidentialité des messages. Il présente les caractéristiques suivantes.
Il s'agit d'une méthode pour générer une paire de clés de chiffrement à clé publique (paire clé publique / clé privée).
public KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2024);
return keyGen.generateKeyPair();
}
Obtenez la clé publique / privée de la paire de clés.
KeyPair keyPair = generateKeyPair();
PublicKey publickey = keyPair.getPublic();
PrivateKey privatekey = keyPair.getPrivate();
Comment crypter le message. Chiffrez à l'aide de la ** clé publique **.
Spécifiez l'algorithme, le mode de bloc et la méthode de remplissage lors de l'acquisition de l'instance Cipher
.
Voir JavaDoc pour la classe Cipher
pour une combinaison d'algorithmes, de modes de bloc et de méthodes de remplissage.
public byte[] encrypto(String plainText, PublicKey publickey) throws GeneralSecurityException {
//Format:"algorithme/Mode bloc/Méthode de remplissage"
Cipher encrypter = Cipher.getInstance("RSA/ECB/PKCS1Padding");
encrypter.init(Cipher.ENCRYPT_MODE, publickey);
return encrypter.doFinal(plainText.getBytes());
}
C'est la méthode de déchiffrement du code. Décryptez à l'aide de la ** clé privée **. Spécifiez l'algorithme, le mode de blocage et la méthode de remplissage comme vous l'avez fait pour le chiffrement.
public String decrypto(byte[] cryptoText, PrivateKey privatekey) throws GeneralSecurityException {
Cipher decrypter = Cipher.getInstance("RSA/ECB/PKCS1Padding");
decrypter.init(Cipher.DECRYPT_MODE, privatekey);
return new String(decrypter.doFinal(cryptoText));
}
La fonction de hachage unidirectionnelle est une technique de détection de falsification de message. Il présente les caractéristiques suivantes.
Comment hacher un message. En Java, les fonctions de hachage à sens unique sont appelées "résumés de messages".
private byte[] hash(String plainText) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
return md.digest(plainText.getBytes());
}
Il s'agit d'une méthode de détection des altérations. Tout ce que vous avez à faire est d'obtenir à nouveau la valeur de hachage et de la comparer.
private boolean verify(String plainText, byte[] givenHash) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] newHash = md.digest(plainText.getBytes());
return Arrays.equals(givenHash, newHash);
}
Le code d'authentification de message (MAC) est une technologie permettant de détecter la falsification et le «spoofing» de message. Il présente les caractéristiques suivantes.
Il s'agit de la méthode de génération de la clé de code d'authentification de message (clé commune).
public SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("HmacSHA256");
return keyGen.generateKey();
}
Comment obtenir la valeur MAC d'un message.
private byte[] mac(String plainText, SecretKey key) throws GeneralSecurityException {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
return mac.doFinal(plainText.getBytes());
}
Il s'agit d'une méthode de détection des altérations. Tout ce que vous avez à faire est d'obtenir à nouveau la valeur MAC et de la comparer.
private boolean verify(String plainText, SecretKey key, byte[] givenMac) throws GeneralSecurityException {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(key);
byte[] newMac = mac.doFinal(plainText.getBytes());
return Arrays.equals(givenMac, newMac);
}
La signature numérique est une technologie permettant de détecter la falsification et le "spoofing" des messages. Il présente les caractéristiques suivantes.
--Utilisez des clés différentes pour l'expéditeur et le destinataire du message
Comment générer une paire de clés de signature numérique (paire clé publique / clé privée).
public KeyPair generateKey() throws NoSuchAlgorithmException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(2024);
return keyGen.generateKeyPair();
}
Obtenez la clé publique / privée de la paire de clés.
KeyPair keyPair = generateKey();
PublicKey publickey = keyPair.getPublic();
PrivateKey privatekey = keyPair.getPrivate();
Comment signer un message. Connectez-vous à l'aide de la ** clé privée **.
public byte[] sign(String plainText, PrivateKey privatekey) throws GeneralSecurityException {
Signature sign = Signature.getInstance("SHA256withRSA");
sign.initSign(privatekey);
sign.update(plainText.getBytes());
return sign.sign();
}
Comment vérifier la signature. Validez à l'aide de la ** clé publique **.
public boolean verify(String plainText, byte[] sign, PublicKey publicKey) throws GeneralSecurityException {
Signature verify = Signature.getInstance("SHA256withRSA");
verify.initVerify(publicKey);
verify.update(plainText.getBytes());
return verify.verify(sign);
}
L'échange de clés Diffie-Hellman est une technologie permettant de partager en toute sécurité une clé commune entre l'expéditeur et le destinataire d'un message. Il présente les caractéristiques suivantes.
La procédure d'échange de clés Diffie-Hellman est compliquée, alors organisons la procédure avant d'expliquer comment l'utiliser en détail. Invitez Alice (expéditeur) et Bob (destinataire) à se présenter pour expliquer la procédure.
Lorsque Alice et Bob échangent des clés, suivez les étapes ci-dessous pour générer une clé commune.
Suivez les étapes décrites ci-dessus pour expliquer comment échanger les clés.
Générez d'abord une paire de clés et obtenez P et G de la paire de clés.
//Génération de paires de clés
public KeyPair generateKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DiffieHellman");
keyGen.initialize(2048);
return keyGen.generateKeyPair();
}
//Obtenez P et G
KeyPair keyPair = generateKeyPair();
DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
DHParameterSpec paramSpec = publicKey.getParams();
BigInteger p = paramSpec.getP();
BigInteger g = paramSpec.getG();
En Java, les valeurs de P et G sont fixes. Consultez la documentation sur les noms d'algorithme standard de l'architecture de chiffrement Java pour les valeurs P et G.
https://docs.oracle.com/javase/jp/8/docs/technotes/guides/security/StandardNames.html#algspec Spécifications de l'algorithme → Algorithme de génération de paires de clés DSA → Valeurs par défaut des paramètres
Envoyez P et G d'Alice à Bob. À ce moment, les valeurs de P et G peuvent être vues par un tiers. Bob générera une paire de clés basée sur les P et G. reçus.
public KeyPair generateKeyPair(BigInteger p, BigInteger g) throws GeneralSecurityException {
DHParameterSpec paramSpec = new DHParameterSpec(p, g);
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DiffieHellman");
keyGen.initialize(paramSpec);
return keyGen.generateKeyPair();
}
Alice obtient la valeur secrète X et la valeur publique Y.
//Obtenez la valeur secrète X
DHPrivateKey privateKey = (DHPrivateKey) keyPair.getPrivate();
BigInteger x = privateKey.getX();
//Obtenir une valeur publique Y
DHPublicKey publicKey = (DHPublicKey) keyPair.getPublic();
BigInteger y = publicKey.getY();
Bob obtient la valeur secrète X et la valeur publique Y. La méthode d'acquisition est la même qu'Alice.
Alice et Bob échangent la valeur publiée Y. À ce stade, la valeur de Y peut être vue par un tiers.
Alice génère une clé commune.
Pour générer la clé commune, utilisez les valeurs de P et G, la valeur publique Y de l'autre partie (Bob) et la clé privée (DHPrivateKey
) de vous-même (Alice).
public SecretKey generateKey(BigInteger p, BigInteger g, BigInteger othersY, DHPrivateKey myPrivateKey)
throws GeneralSecurityException {
//Générer la clé publique de l'autre partie (Bob)
DHPublicKeySpec publicKeySpec = new DHPublicKeySpec(othersY, p, g);
KeyFactory keyFactory = KeyFactory.getInstance("DiffieHellman");
DHPublicKey othersPublicKey = (DHPublicKey) keyFactory.generatePublic(publicKeySpec);
//Générez une clé commune en utilisant la clé publique de l'autre partie (Bob) et la clé privée de vous-même (Alice)
KeyAgreement keyAgreement = KeyAgreement.getInstance("DiffieHellman");
keyAgreement.init(myPrivateKey);
keyAgreement.doPhase(othersPublicKey, true);
SecretKey key = keyAgreement.generateSecret("AES");
return key;
}
Bob génère une clé commune.
Il est généré de la même manière qu'Alice, mais utilise la valeur publique Y d'Alice et la clé privée de Bob (DHPrivateKey
).
PBE -Password Based Encryption-
PBE est une technologie de protection de la confidentialité à l'aide de mots de passe. Il présente les caractéristiques suivantes.
Préparez le sel avant de générer la clé. Salt est un tableau d'octets aléatoires. Salt est utilisé pour empêcher que les mots de passe ne soient piratés par les attaques de dictionnaire.
public byte[] generateSalt() {
SecureRandom random = new SecureRandom();
byte[] salt = new byte[8];
random.nextBytes(salt);
return salt;
}
C'est la méthode pour générer la clé PBE (clé commune). Spécifiez le mot de passe, le sel et le nombre de hachages. En augmentant le nombre de hachages, vous pouvez augmenter le temps de traitement requis pour Brute Force Attack.
public SecretKey generateKey(String password, byte[] salt, int hashCount) throws GeneralSecurityException {
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, hashCount);
SecretKeyFactory keyFac = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_128");
SecretKey key = keyFac.generateSecret(keySpec);
keySpec.clearPassword();
return key;
}
Obtenez les paramètres de l'algorithme sous forme de tableau d'octets et enregistrez-les. Les valeurs telles que le vecteur d'initialisation sont stockées dans les paramètres de l'algorithme.
private byte[] getAlgorithmParameters(SecretKey key) throws GeneralSecurityException, IOException {
Cipher encrypter = Cipher.getInstance("PBEWithHmacSHA256AndAES_128");
encrypter.init(Cipher.ENCRYPT_MODE, key);
AlgorithmParameters params = encrypter.getParameters();
return params.getEncoded();
}
Comment crypter le message. Spécifiez la clé commune et les paramètres d'algorithme.
public byte[] encrypto(String plainText, SecretKey key, byte[] algParam)
throws GeneralSecurityException, IOException {
AlgorithmParameters params = AlgorithmParameters.getInstance("PBEWithHmacSHA256AndAES_128");
params.init(algParam);
Cipher encrypter = Cipher.getInstance("PBEWithHmacSHA256AndAES_128");
encrypter.init(Cipher.ENCRYPT_MODE, key, params);
return encrypter.doFinal(plainText.getBytes());
}
C'est la méthode de déchiffrement du code. Spécifiez la clé commune et les paramètres d'algorithme.
public String decrypto(byte[] cryptoText, SecretKey key, byte[] algParam)
throws GeneralSecurityException, IOException {
AlgorithmParameters params = AlgorithmParameters.getInstance("PBEWithHmacSHA256AndAES_128");
params.init(algParam);
Cipher decrypter = Cipher.getInstance("PBEWithHmacSHA256AndAES_128");
decrypter.init(Cipher.DECRYPT_MODE, key, params);
return new String(decrypter.doFinal(cryptoText));
}
Voici un résumé de ce que j'ai appris sur la cryptographie, qui gagne de plus en plus d'attention en raison de l'essor de la blockchain. Vous pouvez voir que Java couvre diverses techniques cryptographiques.