4

RSA アルゴリズムを使用して文字列を暗号化および復号化しようとしています。ここでは、暗号化はうまく機能していますが、復号化に問題があります。コードは DECRYPT メソッドの doFinal に達すると終了します。入力が間違っていますか、それとも公開鍵と秘密鍵に問題がありますか? これに関する提案をお願いします。ありがとう。

public class rsa 
{   
 private KeyPair keypair;       

 public rsa() throws NoSuchAlgorithmException, NoSuchProviderException 
    {
        KeyPairGenerator keygenerator = KeyPairGenerator.getInstance("RSA");
        SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
        keygenerator.initialize(1024, random);
        keypair = keygenerator.generateKeyPair();
    }
public String ENCRYPT(String Algorithm, String Data ) throws Exception
{   
    String alg = Algorithm;
    String data=Data;
    byte[] encrypted=new byte[2048];
    if(alg.equals("RSA"))
    {   

        PublicKey publicKey = keypair.getPublic();
        Cipher cipher;
        cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
         encrypted = cipher.doFinal(data.getBytes());
        System.out.println("Encrypted String[RSA] -> " + encrypted);
    }
    return encrypted.toString();
}
public String DECRYPT(String Algorithm, String Data ) throws Exception
{   
    String alg = Algorithm;
    byte[] Decrypted=Data.getBytes();


    if(alg.equals("RSA"))
    {   

        PrivateKey privateKey = keypair.getPrivate();
        Cipher cipher;  
        cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] dec = cipher.doFinal(Decrypted);

        System.out.println("Decrypted String[RSA] -> " + dec.toString());

    }
    return Decrypted.toString();
}
public static void main(String[] args) throws Exception
{
    rsa RSA=new rsa();
    RSA.ENCRYPT("RSA", "avinash");
    RSA.DECRYPT("RSA","[B@cb7e2c");
}

}

 got exception as

Exception in thread "main" javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(Unknown Source)
at sun.security.rsa.RSAPadding.unpad(Unknown Source)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
at javax.crypto.Cipher.doFinal(Cipher.java:2086)
at EncryptionProvider.rsa.DECRYPT(rsa.java:56)
at EncryptionProvider.rsa.main(rsa.java:68)

暗号化された文字列[RSA] -> [B@4a96a

4

2 に答える 2

9

[B@cb7e2c暗号化の出力ではありません。toString()これは、byte[] オブジェクトに対して出力または呼び出しを試みた結果です。(例えば、 の結果を見てくださいSystem.out.println(new byte[0]);)

暗号化された byte[] を復号化関数に直接フィードしてみてnew String(dec)、結果を出力するために使用します。暗号化されたデータを文字列として表示/保存する場合は、16 進数または base64 としてエンコードします。

ここが見分け方です。byte[]バイト配列を意味します。これはバイナリ データであり、一連の 8 ビットの符号付き数値です。ascii のみの操作に慣れている場合、一連のbytes と a の違いStringは些細なことに思えるかもしれませんが、文字列をバイナリで表現する方法はたくさんあります。あなたが行っている暗号化と復号化は、文字列がどのように見えるか、またはデータが文字列を表しているかどうかはまったく気にしません。それはビットを見ているだけです。

文字列を暗号化する場合は、一連のバイトに変換する必要があります。一方、文字列を構成するバイトを復号化したら、元に戻す必要があります。 myString.getBytes()多くのnew String(myBytea)場合効果的ですが、デフォルトのエンコーディングを使用するだけなので、少しずさんです。アリスのシステムが utf-8 を使用し、ボブのシステムが utf-16 を使用した場合、彼女のメッセージは彼にとってあまり意味がありません。そのため、たとえば と を使用して文字エンコーディングを指定するのが常に最善myString.getBytes("utf-8")ですnew String(myBytea,"utf-8")

私が取り組んでいるプロジェクトのいくつかの関数と、デモmain関数を次に示します。

import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.xml.bind.DatatypeConverter;

public class RSAExample {
    private static byte[] h2b(String hex){
        return DatatypeConverter.parseHexBinary(hex);
    }
    private static String b2h(byte[] bytes){
        return DatatypeConverter.printHexBinary(bytes);
    }

    private static SecureRandom sr = new SecureRandom();

    public static KeyPair newKeyPair(int rsabits) throws NoSuchAlgorithmException {
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
        generator.initialize(rsabits, sr);
        return generator.generateKeyPair();
    }

    public static byte[] pubKeyToBytes(PublicKey key){
        return key.getEncoded(); // X509 for a public key
    }
    public static byte[] privKeyToBytes(PrivateKey key){
        return key.getEncoded(); // PKCS8 for a private key
    }

    public static PublicKey bytesToPubKey(byte[] bytes) throws InvalidKeySpecException, NoSuchAlgorithmException{
        return KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(bytes));
    }
    public static PrivateKey bytesToPrivKey(byte[] bytes) throws InvalidKeySpecException, NoSuchAlgorithmException{
        return KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(bytes));
    }

    public static byte[] encryptWithPubKey(byte[] input, PublicKey key) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher.doFinal(input);
    }
    public static byte[] decryptWithPrivKey(byte[] input, PrivateKey key) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher.doFinal(input);
    }


    public static void main(String[] args) throws Exception {
        KeyPair kp = newKeyPair(1<<11); // 2048 bit RSA; might take a second to generate keys
        PublicKey pubKey = kp.getPublic();
        PrivateKey privKey = kp.getPrivate();
        String plainText = "Dear Bob,\nWish you were here.\n\t--Alice";
        byte[] cipherText = encryptWithPubKey(plainText.getBytes("UTF-8"),pubKey);
        System.out.println("cipherText: "+b2h(cipherText));
        System.out.println("plainText:");
        System.out.println(new String(decryptWithPrivKey(cipherText,privKey),"UTF-8"));
    }
}
于 2012-04-19T05:32:15.837 に答える