[Java] Utiliser la technologie cryptographique avec les bibliothèques standard

Liste des technologies cryptographiques présentées dans cet article

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.

Code symétrique

Qu'est-ce que le code symétrique?

Le cryptage symétrique est une technologie de protection de la confidentialité des messages. Il présente les caractéristiques suivantes.

Comment utiliser le cryptage symétrique

Génération de clés

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();
    }

Génération du vecteur d'initialisation

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);
    }

Cryptage des messages

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());
    }

Décryptage du code

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));
    }

Chiffrement à clé publique

Qu'est-ce que le chiffrement à clé publique?

Le cryptage à clé publique est une technologie permettant de protéger la confidentialité des messages. Il présente les caractéristiques suivantes.

Comment utiliser le chiffrement à clé publique

Génération de clés

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();

Cryptage des messages

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());
    }

Décryptage du code

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));
    }

Fonction de hachage unidirectionnelle

Qu'est-ce qu'une fonction de hachage unidirectionnelle?

La fonction de hachage unidirectionnelle est une technique de détection de falsification de message. Il présente les caractéristiques suivantes.

Comment utiliser la fonction de hachage unidirectionnelle

Hachage de message

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());
    }

Détection de falsification

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);
    }

Code de vérification du message

Qu'est-ce qu'un code de vérification de message?

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.

Comment utiliser le code de vérification des messages

Génération de clés

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();
    }

Obtenez la valeur MAC

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());
    }

Détection de falsification

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);
    }

Signature numérique

Qu'est-ce qu'une signature numérique?

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 utiliser la signature numérique

Génération de clés

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();

Signez le message

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();
    }

Vérification de la signature

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);
    }

Échange de clés Diffie-Hellman

Qu'est-ce que l'échange de clés Diffie-Hellman?

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.

Procédure d'échange de clés Diffie-Hellman

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.

  1. Alice génère un grand nombre premier P et une source G
  2. Envoyez P et G d'Alice à Bob
    1. Alice obtient la valeur secrète X et la valeur publique Y Quatre. Bob obtient la valeur secrète X et la valeur publique Y Cinq. Alice et Bob échangent la valeur publique Y
  3. Alice génère une clé commune
  4. Bob génère une clé commune

Comment utiliser l'échange de clés Diffie-Hellman

Suivez les étapes décrites ci-dessus pour expliquer comment échanger les clés.

1. Alice génère un grand nombre premier P et une source G

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

2. Envoyez P et G d'Alice à Bob

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();
    }

3. Alice obtient la valeur secrète X et la valeur publique Y

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();

4. Bob obtient la valeur secrète X et la valeur publique Y

Bob obtient la valeur secrète X et la valeur publique Y. La méthode d'acquisition est la même qu'Alice.

Cinq. Alice et Bob échangent la valeur publique Y

Alice et Bob échangent la valeur publiée Y. À ce stade, la valeur de Y peut être vue par un tiers.

6. Alice génère une clé commune

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;
    }

7. Bob génère une clé commune

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-

Qu'est-ce que PBE

PBE est une technologie de protection de la confidentialité à l'aide de mots de passe. Il présente les caractéristiques suivantes.

Comment utiliser PBE

Production de sel

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;
    }

Génération de clés

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;
    }

Enregistrement des paramètres d'algorithme

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();
    }

Cryptage des messages

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());
    }

Décryptage du code

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));
    }

À la fin

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.

Recommended Posts

[Java] Utiliser la technologie cryptographique avec les bibliothèques standard
Utiliser OpenCV avec Java
Utiliser PreparedStatement en Java
Utilisez une bibliothèque Java externe pour le moment
Essayez d'ajouter du texte à une image avec Scala en utilisant la bibliothèque standard de Java
Lire l'entrée standard en Java
Essayez le hooking global en Java à l'aide de la bibliothèque JNativeHook
Code à utiliser lorsque vous souhaitez traiter Json en Java avec uniquement des bibliothèques standard
Accéder à l'interface réseau avec Java
Devinez le code de caractère en Java
Utiliser Microsoft Graph avec Java standard
Spécifiez l'emplacement Java dans eclipse.ini
Chiffrer à l'aide du chiffrement RSA en Java
Utilisons Twilio en Java! (Introduction)
Décompressez le fichier zip en Java
[Java] N'utilisez pas "+" dans append!
Utilisez des clés composites dans Java Maps.
Utiliser le plugin Findbugs dans Eclipse
Bienvenue dans le marais des bibliothèques Java! !!
Analyser l'analyse syntaxique de l'API COTOHA en Java
Comment utiliser les classes en Java?
Utilisez-vous Stream en Java?
Appelez la super méthode en Java
Créez un serveur Web simple avec la bibliothèque standard Java com.sun.net.httpserver
Obtenez le résultat de POST en Java
Prise en charge multilingue de Java Comment utiliser les paramètres régionaux
Utilisez OpenCV_Contrib (ArUco) avec Java! (Partie 2-Programmation)
[Java] Comment utiliser la classe File
Référence Java à comprendre dans la figure
Essayez d'utiliser l'API Stream en Java
Appelez l'API de notification Windows en Java
Bibliothèque de tests unitaires Java Artery-Easy to use
J'ai essayé le nouveau yuan à Java
Etudier comment utiliser le constructeur (java)
Organisation des notes dans la tête (Java-Arrangement)
[Traitement × Java] Comment utiliser la boucle
Essayez d'appeler le service CORBA sur Java 11+
Utilisez "Rhino" qui exécute JavaScript en Java
Point 72: Favoriser l'utilisation d'exceptions standard
Quelle est la méthode principale en Java?
[Traitement × Java] Comment utiliser la classe
Comment obtenir la date avec Java
J'ai essayé la bibliothèque AutoValue avec Intellij
[Traitement × Java] Comment utiliser la fonction
L'histoire de l'écriture de Java dans Emacs
Entrée de la console en Java (comprendre le mécanisme)
[Java] Colorez la sortie standard vers le terminal
[Java] Comment utiliser la classe Calendar
Qu'est-ce qui n'était pas une utilisation équitable du détournement d'API Java sur Android?
Est-il possible de mettre la bibliothèque (aar) dans la bibliothèque Android (aar) et de l'utiliser?
Utilisez JDBC Manager avec les paramètres de jdbc.dicon.
L'histoire de la comparaison de chaînes de bas niveau en Java
[Java] Gestion des Java Beans dans la chaîne de méthodes
À propos de la confusion observée dans les serveurs Java de démarrage
Présentation de la bibliothèque
L'histoire de la fabrication d'un Othello ordinaire à Java
À propos de l'idée des classes anonymes en Java