3

公開鍵で RSA を使用して JavaScript で小さな文字列を暗号化し、秘密鍵を使用して Java サーバー側コードでその文字列を復号化したいと考えています。

私は JavaScript でこのコードを使用しています: http://www-cs-students.stanford.edu/~tjw/jsbn/ の例: http://www-cs-students.stanford.edu/~tjw/jsbn/rsa2 .html

Java側のこのコード: Javascriptで文字列を暗号化し、Javaで復号化する

両方のコードは独立してうまく機能しますが、お互いを理解していません。今日これを解決する必要があります。そうしないと、このように機能する他の非対称アルゴリズムを受け入れることができます。

4

2 に答える 2

3

Java 側で raw 暗号化を使用し、Java Card 側で PKCS#1 v1.5 パディングを使用して RSA 暗号化を使用しています。を通じて Java RSA を試して使用する必要がありますjavax.crypto.Cipher.getInstance("RSA/None/PKCS1Padding")。Base 64 エンコーディングが存在する場合は、それを削除することを忘れないでください。

于 2013-09-23T18:42:05.027 に答える
3

後の世代のために例を残したい:)

まず、Java コードで鍵ペアを生成する必要があります

KeyPairGenerator kpg;
    try {
        kpg = KeyPairGenerator.getInstance("RSA");
        kpg.initialize(2048);
        KeyPair kp = kpg.genKeyPair();
        yourVariablePublic = kp.getPublic();
        yourVariablePublic = kp.getPrivate();
    } catch(NoSuchAlgorithmException e) {

    }

それでは、現在のページの Java コードに移りましょう。

// receiving public key from where you store it
    Key publicKey = YourCarrierClass.getYourVariablePublic();
    KeyFactory fact;
    // initializing public key variable
    RSAPublicKeySpec pub = new RSAPublicKeySpec(BigInteger.ZERO, BigInteger.ZERO);
    try {
        fact = KeyFactory.getInstance("RSA");
        pub = fact.getKeySpec(publicKey,    RSAPublicKeySpec.class);
    } catch(NoSuchAlgorithmException e1) {
    } catch(InvalidKeySpecException e) {
    }

// now you should pass Modulus string onto your html(jsp) in such way
String htmlUsedModulus = pub.getModulus().toString(16);
// send somehow this String to page, so javascript can use it

JavaScript側の場合:

function sendPassword() {
    var password = $('#passwordField').val();
    var rsa = new RSAKey();
    rsa.setPublic($('#keyModulus').text(), '10001');
    var res = rsa.encrypt(password);
    $('#ajaxSentPassword').val(res);
}

Javaコードで復号化するには:

 Key privateKey = YourCarrierClass.getYourVariablePrivate();
 Cipher cipher;
 BigInteger passwordInt = new BigInteger(ajaxSentPassword, 16);
 byte[] dectyptedText = new byte[1];
 try {
   cipher = javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding");
   byte[] passwordBytes = passwordInt.toByteArray();
   cipher.init(Cipher.DECRYPT_MODE, privateKey);
   dectyptedText = cipher.doFinal(passwordBytes);
   } catch(NoSuchAlgorithmException e) {
   } catch(NoSuchPaddingException e) { 
   } catch(InvalidKeyException e) {
   } catch(IllegalBlockSizeException e) {
   } catch(BadPaddingException e) {
   }
   String passwordNew = new String(dectyptedText);
   System.out.println("Password new " + passwordNew);

ほら、ごめんなさい、私はこれらのキャッチ句を扱うのが苦手です。

================================================== ==================

Upd: ここで、このコードに関するいくつかの問題を発見しました。まず、アルゴリズムを変更できます

javax.crypto.Cipher.getInstance("RSA/ECB/PKCS1Padding");

に:

javax.crypto.Cipher.getInstance("RSA");

ただし、これは必須ではなく、両方で機能します。今、本当の問題はこの行に関するものです

byte[] passwordBytes = passwordInt.toByteArray();

ここで、BigInteger からバイト配列を生成すると、前に [0] が符号として追加されることがあります (そうでない場合もあるので、アルゴリズムはその配列を解読できます)。そのため、バイト配列のサイズは 65/129/257 になり、アルゴリズムでは解読できません。 IllegalBlockSizeException をスローします。この問題については、モジュラス RSA キーで 1 バイト余分に取得する で説明されており、指数についても質問されることがあります。最も簡単な解決策は、配列からそのゼロを捨てることです:

    byte[] byteArray = new byte[256];

    BigInteger passwordInt = new BigInteger(password, 16);
    if (passwordInt.toByteArray().length > 256) {
        for (int i=1; i<257; i++) {
            byteArray[i-1] = passwordInt.toByteArray()[i];
        }
    } else {
        byteArray = passwordInt.toByteArray();
    }
于 2014-02-04T12:48:11.557 に答える