Java RSA pourquoi un texte de chiffrement différent à chaque fois?


Je développe un module de connexion avec JSP/Servlets/MySQL avec l'algorithme RSA. Une fois que j'enregistre un nouvel utilisateur, j'enregistre le PublicKey dans MySQL et crypte un mot de passe avec.

Lorsque l'utilisateur essaie de se connecter, je récupère ce PublicKey et crypte le mot de passe qui vient d'être tapé avec le PublicKey correspondant et le compare avec le mot de passe crypté précédemment enregistré, mais il renvoie toujours un texte de chiffrement différent.

Je ne peux pas comprendre pourquoi j'obtiens différents mots de passe cryptés chaque fois. Est-ce que je fais mal? Génère-t-il un nouveau PublicKey chaque fois qu'il exécute la "keyFactory.generatePublic"?

Merci pour votre aide

Ma méthode pour générer une clé publique est:

    public byte[] generateBytePublicKey() throws Exception {
        byte[] pk = null;

        try {
            final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
            keyGen.initialize(1024);
            pk = keyGen.generateKeyPair().getPublic().getEncoded();
        } (...... etc etc)
        return pk;

Ma méthode pour crypter un mot de passe:

    public byte[] encryptBytes(String pwd, byte[] key) throws Exception {

        byte[] cipherText = null;
        PublicKey pk;

        try {
            byte[] dataBytes = pwd.getBytes();
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            pk = keyFactory.generatePublic(new X509EncodedKeySpec(key));
            final Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pk);
            cipherText = cipher.doFinal(dataBytes);
        } (..... etc etc)
            return cipherText;

Ma méthode pour stocker le mot de passe crypté et la clé publique dans une table MySQL:

    (.....................)
    try {
        Statement stmt = null; 
        ResultSet rs = null;
        byte[] bytePublicKey;
        byte[] cipherPwd;

        bytePublicKey = generateBytePublicKey();
        cipherPwd = encryptBytes(password, bytePublicKey);

        String query = "INSERT INTO Users (email, pwd, publickey) VALUES ('" + email + "', ?, ?)";
        PreparedStatement ps;
        ps = conn.getConexion().prepareStatement(query);
        ps.setBytes(1, cipherPwd);
        ps.setBytes(2, bytePublicKey);
        resultSet = ps.executeUpdate();
   } (............. etc etc)

Ma méthode pour vérifier si un utilisateur est valide:

   public boolean isUserValid (String email, String typedPassword) throws Exception {

    byte[] storedBytesPassword;
    byte[] storedBytesPublicKey;
    byte[] typedPwdtoBytes;

    try {
        storedBytesPublicKey = getByteArrays(email, "publicKey");
        storedBytesPassword = getByteArrays(email, "pwd");

        typedPwdtoBytes = encryptBytes(typedPassword, storedBytesPublicKey);

        return Arrays.equals(typedPwdtoBytes, storedBytesPassword);
   } (............. etc etc)

Ma méthode pour obtenir les tableaux d'octets de la table MySQL:

  public byte[] getByteArrays (String email, String byteArray) throws SQLException {

    (..............)

    try {
        Statement stmt=null; 
        ResultSet rs=null;

        query = "SELECT " + byteArray + " FROM Users WHERE email = '" + email + "'";

        try {
            stmt = (conn.getConexion()).createStatement(); 
            rs = stmt.executeQuery(query);
            while (rs.next() ) {
                bytesArr = rs.getBytes(1);
        } (.................. etc etc)
Author: Miguel R Arriaga Solar, 2015-11-07

1 answers

Lorsque vous ne spécifiez pas la transformation complète, vous obtenez les valeurs par défaut du fournisseur, ce qui pour RSA est probable RSA/ECB/PKCS1Padding.

PKCS1Padding (voir Padding schemes ) signifie que des données aléatoires sont ajoutées pour s'assurer que le chiffrement deux fois du même texte brut générera un texte chiffré différent.

Les chiffrements servent à chiffrer et à déchiffrer. Puisque vous n'avez pas l'intention de décrypter un mot de passe, le chiffrement n'est pas le bon choix pour vous.

Pour le "chiffrement" à sens unique, utilisez un message digest, également appelé fonction de hachage Cryptographique. Ils fonctionnent comme la méthode Java hashCode() en générant un hachage/résumé du texte en clair, mais contrairement à hashCode(), un résumé est beaucoup plus complexe afin de s'assurer que le texte en clair ne peut pas être déduit de la valeur du résumé.

Comme il s'agit d'un algorithme à sens unique, vous pouvez stocker la clé et la valeur de résumé ensemble. Le but d'un résumé assurez-vous que vous êtes assuré d'obtenir toujours la même valeur de résumé à partir du même texte en clair / clé combinaison.

, Vous pouvez même utiliser la même clé pour tous les mots de passe. Rappelez-vous que c'est irréversible, tant que l'algorithme digest est assez fort, par exemple SHA-256.

 1
Author: Andreas, 2015-11-07 06:54:18