2

Java で RSA 暗号化を使用しようとしています。

公開鍵を生成し、それを使用してテキストを暗号化しています。私の問題は、同じテキストと同じキーを 2 回渡すと、暗号化された結果が異なることです。これは、入力されたテキストが以前の暗号化の保存結果と等しいかどうかをテストするために暗号化を使用できないことを意味します。

これは私の暗号化クラスです:

   import java.security.InvalidKeyException;
   import java.security.KeyPair;
   import java.security.KeyPairGenerator;
   import java.security.NoSuchAlgorithmException;
   import java.security.PublicKey;
   import java.util.Arrays;

   import javax.crypto.BadPaddingException;
   import javax.crypto.Cipher;
   import javax.crypto.IllegalBlockSizeException;
   import javax.crypto.NoSuchPaddingException;
   /**
    * The class encrypts text using an RSA algorithm.
    *
    */
   public class RSAEncryption {
       //RSA algorithm
       private final String ALGORITHM = "RSA";

/**
 * The generateKey method generates a public key for use in RSA encryption.
 * @return key a PublicKey for use in RSA encryption.
 */
public PublicKey generateKey(){
    KeyPair key = null;
    KeyPairGenerator keyGen;
    try {
        keyGen = KeyPairGenerator.getInstance(ALGORITHM); //gets instance of the alogrithm
        keyGen.initialize(1024); //a 1021 bit key
        key = keyGen.generateKeyPair(); //makes a pair
    } catch (NoSuchAlgorithmException e) {

        e.printStackTrace();
    }
    return key.getPublic(); //returns the public key. Private key never stored.
}

    /**
    * The encrypt method takes in text and a key and encrypts the text using the RSA encryption algorithm.
    * @params text a String, the text to encrypt.
    * @params key a PublicKey to use in encryption.
    * @returns encryptedText a byte array representing the result of the encryption.

public byte[] encrypt(String text, PublicKey key){
    byte[] encryptedText = null;
    Cipher cipher;
    try {
        cipher = Cipher.getInstance(ALGORITHM); //gets instance of RSA
        cipher.init(Cipher.ENCRYPT_MODE, key); //in encryption mode with the key
        encryptedText = cipher.doFinal(text.getBytes()); //carry out the encryption
    } catch (NoSuchAlgorithmException e) {          
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {            
        e.printStackTrace();
    } catch (IllegalBlockSizeException e) {         
        e.printStackTrace();
    } catch (BadPaddingException e) {           
        e.printStackTrace();
    } catch (InvalidKeyException e) {       
        e.printStackTrace();
    }
    return encryptedText; //return encrypted result
}

/**
 * The authenticate method checks if entered text, once encrypted, matches the stored byte[].
 * @param text a String, the text to encrypt.
 * @param stored a byte[], the result of a prior encryption.
 * @param key a PublicKey, a result of the generateKey method.
 * @return boolean, true if the text is valid, false otherwise.
 */

public boolean authenticate(String text, byte[] stored, PublicKey key){
    byte[] encryptText = encrypt(text,key); //encrypt the entered text
    return Arrays.equals(stored, encryptText); //check if the stored and entered byte[] are the same.
}
} 

このための JUnit テストを作成しました。

import static org.junit.Assert.*;

import java.security.PublicKey;
import java.util.Arrays;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;


public class RSAEncryptionTest {

RSAEncryption cipher;
String text;

@Before
public void setUp(){
    cipher = new RSAEncryption();
    text = "text";
}

@Test
public void testEncryptionGenerateKeyGeneratesANewKeyWhenCalled(){

    PublicKey key = cipher.generateKey();

    assertEquals(false,key.equals(cipher.generateKey()));
}

@Test
public void testEncryptionEncryptMethodRepeatablyEncrypts(){

    PublicKey key = cipher.generateKey();

    byte[] encrypted = cipher.encrypt(text,key);
    Assert.assertArrayEquals(encrypted, cipher.encrypt(text,key));
    //test fails
}


@Test
public void testEncryptionAuthenticateMethodReturnsTrueWhenValidTextPassedIn(){

    PublicKey key = cipher.generateKey();

    byte[] encrypted = cipher.encrypt(text,key);

    assertEquals(true,cipher.authenticate(text,encrypted,key));
            //test fails
}


@Test
public void testEncryptionAuthenticateMethodReturnsFalseWhenInvalidTextPassedIn(){

    PublicKey key = cipher.generateKey();

    byte[] encrypted = cipher.encrypt(text,key);

    assertEquals(false,cipher.authenticate("text1",encrypted,key)); 
} 

}

2 番目と 3 番目のテストは失敗します。

RSAを使用してテキストを繰り返し暗号化する方法はありますか?

4

2 に答える 2

3

RSA は公開鍵暗号方式です。実際にはハッシュ アルゴリズム (SHA-256 や SHA-512 など) を使用したいようです。私がこれを言うのは、あなたがこう言うからです:

これは、入力されたテキストが以前の暗号化の保存結果と等しいかどうかをテストするために暗号化を使用できないことを意味します。

これが目標である場合は、ハッシュ アルゴリズムを使用する必要があります。設計上、RSA 暗号化には、暗号文が異なることを確認するためのパディング ステップを含める必要があります。

これらの問題を回避するために、実際の RSA 実装では通常、値 m を暗号化する前に、何らかの形式の構造化されたランダム化されたパディングを値に埋め込みます。このパディングにより、m が安全でない平文の範囲に入らないことが保証され、指定されたメッセージがパディングされると、多数の異なる可能な暗号文の 1 つに暗号化されます。

-- http://en.wikipedia.org/wiki/RSA_%28algorithm%29

于 2013-08-10T18:10:52.577 に答える
2

RSA 暗号の出力は、適切なパディング スキーム (通常は PKCS#1 または OAEP パディング) を使用する場合、特定の平文に対して毎回同じではありません。特定の平文を暗号化すると、毎回異なる暗号文が生成されます。暗号が特定の入力に対して毎回同じ出力を生成すると、セキュリティ上の脆弱性が生じます。

Cipher.getInstance(String). _ そうすることでテストに合格することになりますが、前述したように、これはあまり安全ではありません。

于 2013-08-10T18:09:24.530 に答える