[JAVA] Essayez le cryptage / décryptage de la chaîne Spring Security AES256

Aperçu

Au travail, j'ai parfois réfléchi à la manière de gérer des projets qui supposent un cryptage / décryptage de données, j'écrirai donc que je l'ai essayé pour rappel.

Informations de référence

Anglais mais la documentation spring.io est utile spring.io - Documentation sur les crypteurs

Les documents TERASOLUNA sont faciles à lire en japonais 6. Mesures de sécurité de TERASOLUNA Server Framework for Java (5.x) >> 6.9. Chiffrement

Conclusion (soudainement)

De la conclusion, cela ressemble à ce qui suit (seulement mon avis personnel)

Méthode Contenu Mode cryptographique Force de cryptage
noOpText Ne cryptez pas. Il est utilisé comme maquette pour le montage. Aucun hors de question
queryableText Utilisez un cryptage «standard» basé sur un mot de passe. Générez une valeur invariante. CBC Faible
text Utilisez un cryptage «standard» basé sur un mot de passe. Générez une valeur variable. CBC Pendant ~
delux Utilisez un cryptage basé sur un mot de passe «plus fort». Générez une valeur variable. GCM Haute

Vérification

Créez l'exemple suivant et essayez-le.

public class EncryptorTest {

  private static String secret = "1234";
  private static String salt = "5678";

  public static void main(String[] args) throws IOException {

    String text = "Hello";

    TextEncryptor encryptor1 = Encryptors.noOpText();
    String noOpTextEncryptText = encryptor1.encrypt(text);
    String noOpTextDecryptText = encryptor1.decrypt(noOpTextEncryptText);

    TextEncryptor encryptor2 = Encryptors.queryableText(secret, salt);
    String queryableTextEncryptText = encryptor2.encrypt(text);
    String queryableTextDecryptText = encryptor2.decrypt(queryableTextEncryptText);

    TextEncryptor encryptor3 = Encryptors.text(secret, salt);
    String textEncryptText = encryptor3.encrypt(text);
    String textDecryptText = encryptor3.decrypt(textEncryptText);

    TextEncryptor encryptor4 = Encryptors.delux(secret, salt);
    String deluxEncryptText = encryptor4.encrypt(text);
    String deluxDecryptText = encryptor4.decrypt(deluxEncryptText);

    System.out.println("noOpText()      :");
 System.out.println ("chaîne de chiffrement:" + noOpTextEncryptText);
 System.out.println ("Confirmation de déchiffrement:" + noOpTextDecryptText);
    System.out.println("");
    System.out.println("queryableText() : ");
 System.out.println ("chaîne de chiffrement:" + queryableTextEncryptText);
 System.out.println ("Confirmation de déchiffrement:" + queryableTextDecryptText);
    System.out.println("");
    System.out.println("text()          : ");
 System.out.println ("chaîne de chiffrement:" + textEncryptText);
 System.out.println ("Confirmation de déchiffrement:" + textDecryptText);
    System.out.println("");
    System.out.println("delux()         : ");
 System.out.println ("chaîne de chiffrement:" + deluxEncryptText);
 System.out.println ("Confirmation de déchiffrement:" + deluxDecryptText);
  }
noOpText()      :
Chaîne chiffrée: Bonjour
Confirmation de déchiffrement: Bonjour

queryableText() : 
Chaîne chiffrée: 524110739525b3f266a0064b4229a77d
Confirmation de déchiffrement: Bonjour

text()          : 
Chaîne chiffrée: ced1eb40b88e691f502d548ed17752bff82592da917804ea66ea1a49bfa77033
Confirmation de déchiffrement: Bonjour

delux()         : 
Chaîne chiffrée: 61e62f473d0cb228305081b927a3225d487a749b87af62071ad60dc6b27703410de45f7fbf
Confirmation de déchiffrement: Bonjour

Bien que les longueurs de caractères des cryptages soient différentes, on peut voir que le décryptage à partir du cryptage est possible dans chaque cas. Jetons un coup d'œil à la logique de chaque méthode ici pour voir quelle est la différence.

noOpText Si vous créez une instance avec Encryptors.noOpText () La logique suivante est appelée.

  private static final class NoOpTextEncryptor implements TextEncryptor {

    public String encrypt(String text) {
      return text;
    }

    public String decrypt(String encryptedText) {
      return encryptedText;
    }

  }

J'ai dit que c'était hors de question, mais je n'ai rien fait. Y a-t-il une utilité pour cela ...

queryableText

Puis ** queryableText **

	public static TextEncryptor queryableText(CharSequence password, CharSequence salt) {
		return new HexEncodingTextEncryptor(new AesBytesEncryptor(password.toString(),
				salt));
	}
	public AesBytesEncryptor(String password, CharSequence salt) {
 this (mot de passe, sel, null); // ← L'argument ici est nul
	}

	public AesBytesEncryptor(String password, CharSequence salt,
			BytesKeyGenerator ivGenerator) {
		this(password, salt, ivGenerator, CipherAlgorithm.CBC);
	}

	public AesBytesEncryptor(String password, CharSequence salt,
			BytesKeyGenerator ivGenerator, CipherAlgorithm alg) {
		PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), Hex.decode(salt),
				1024, 256);
		SecretKey secretKey = newSecretKey("PBKDF2WithHmacSHA1", keySpec);
		this.secretKey = new SecretKeySpec(secretKey.getEncoded(), "AES");
		this.alg = alg;
		this.encryptor = alg.createCipher();
		this.decryptor = alg.createCipher();
		this.ivGenerator = ivGenerator != null ? ivGenerator : alg.defaultIvGenerator();
	}

text

Laissez le commentaire de ** queryableText ** et laissez ** text **

	public static TextEncryptor text(CharSequence password, CharSequence salt) {
		return new HexEncodingTextEncryptor(standard(password, salt));
	}

	public static BytesEncryptor standard(CharSequence password, CharSequence salt) {
		return new AesBytesEncryptor(password.toString(), salt,
 KeyGenerators.secureRandom (16)); // ← L'argument ici est un nombre aléatoire
	}
	public AesBytesEncryptor(String password, CharSequence salt,
			BytesKeyGenerator ivGenerator) {
		this(password, salt, ivGenerator, CipherAlgorithm.CBC);
	}

	public AesBytesEncryptor(String password, CharSequence salt,
			BytesKeyGenerator ivGenerator, CipherAlgorithm alg) {
		PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), Hex.decode(salt),
				1024, 256);
		SecretKey secretKey = newSecretKey("PBKDF2WithHmacSHA1", keySpec);
		this.secretKey = new SecretKeySpec(secretKey.getEncoded(), "AES");
		this.alg = alg;
		this.encryptor = alg.createCipher();
		this.decryptor = alg.createCipher();
		this.ivGenerator = ivGenerator != null ? ivGenerator : alg.defaultIvGenerator();
	}

Quelle est la différence entre ** queryableText ** et ** text ** La différence est de savoir s'il faut passer le BytesKeyGenerator en tant que ** null ** ou ** KeyGenerators.secureRandom (16) **.

Puisque ** queryableText ** est passé en tant que ** null **, la même chaîne chiffrée est générée à chaque fois. Puisque ** text ** passe ** KeyGenerators.secureRandom (16) **, un nombre aléatoire différent est généré à chaque fois, et par conséquent, une chaîne de caractères chiffrée différente est générée à chaque fois.

delux

Et enfin ** delux **

	public static TextEncryptor delux(CharSequence password, CharSequence salt) {
		return new HexEncodingTextEncryptor(stronger(password, salt));
	}

	public static BytesEncryptor stronger(CharSequence password, CharSequence salt) {
		return new AesBytesEncryptor(password.toString(), salt,
				KeyGenerators.secureRandom(16), CipherAlgorithm.GCM);
	}
	public AesBytesEncryptor(String password, CharSequence salt,
			BytesKeyGenerator ivGenerator, CipherAlgorithm alg) {
		PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), Hex.decode(salt),
				1024, 256);
		SecretKey secretKey = newSecretKey("PBKDF2WithHmacSHA1", keySpec);
		this.secretKey = new SecretKeySpec(secretKey.getEncoded(), "AES");
		this.alg = alg;
		this.encryptor = alg.createCipher();
		this.decryptor = alg.createCipher();
		this.ivGenerator = ivGenerator != null ? ivGenerator : alg.defaultIvGenerator();
	}

Quelle est la différence entre ** text ** et ** delux ** La différence est de savoir si ** CBC ** ou ** GCM ** est spécifié pour CipherAlgorithm.

On dit généralement que GCM (Galois / Counter Mode) est capable de traitement parallèle et est plus efficace que CBC. Malgré la mise en œuvre d'un cryptage plus élevé que CBC, il n'y a pas beaucoup de différence dans le temps de traitement.

En fait, écrivez un processus qui répète le cryptage → le décryptage 10000 fois et échantillonnez-le plusieurs fois. J'ai comparé ** text ** et ** delux **, mais le temps de traitement était presque le même. (Erreur inférieure à 1 seconde)

Impressions

J'ai pensé qu'il serait préférable d'utiliser ** delux ** sauf s'il y avait une raison spécifique. (Il y a peu de systèmes qui disent que la capacité du disque est ... parce que la longueur des données devient longue à cette époque.)

C'est la fin de ce procès

Recommended Posts

Essayez le cryptage / décryptage de la chaîne Spring Security AES256
Essayez d'utiliser Spring Boot Security
Essayez l'authentification LDAP avec Spring Security (Spring Boot) + OpenLDAP
Essayez de travailler avec Keycloak en utilisant Spring Security SAML (Spring 5)
À propos de l'authentification Spring Security
Spring Security soulève 403 interdits
Essayez d'utiliser Spring JDBC