0

私は RSA 暗号化を使用して Android アプリケーションに取り組んでいます。

サーバー、秘密鍵、友人の公開鍵から取得できます。

秘密鍵は次のようになります。

{"n":"...","d":"...","p":"...","q":"...","dmp1":"...","dmq1":"...","coeff":"..."} (jsbn json format)

modulus => n
public exponent => e
private exponent => d
prime1 => p
prime2 => q
exponent1 => dmp1
exponent2 => dmq1
coefficient => coeff

このキーを使用して、サーバーから受信し、JavaScript ライブラリ (SJCL) によって既に暗号化されているメッセージを復号化する必要があります。また、javascrypt ライブラリを使用してメッセージを復号化できるようにするには、メッセージを暗号化する必要があります。

今のところ、私はこれを行いました:

 public static String decrypt (String data, String stringKey) throws Exception {
        JSONObject jsonKey = new JSONObject(stringKey);

        BigInteger n = new BigInteger(Base64.decode(jsonKey.getString("n"), Base64.DEFAULT));
        BigInteger e = new BigInteger("10001");
        BigInteger d = new BigInteger(Base64.decode(jsonKey.getString("d"), Base64.DEFAULT));
        BigInteger p = new BigInteger(Base64.decode(jsonKey.getString("p"), Base64.DEFAULT));
        BigInteger q = new BigInteger(Base64.decode(jsonKey.getString("q"), Base64.DEFAULT));
        BigInteger dmp1 = new BigInteger(Base64.decode(jsonKey.getString("dmp1"), Base64.DEFAULT));
        BigInteger dmq1 = new BigInteger(Base64.decode(jsonKey.getString("dmq1"), Base64.DEFAULT));
        BigInteger coeff = new BigInteger(Base64.decode(jsonKey.getString("coeff"), Base64.DEFAULT));


        KeySpec privateKeySpec = new RSAPrivateCrtKeySpec(n, e, d, p, q, dmp1, dmq1, coeff);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec);

        Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] dec = cipher.doFinal(data.getBytes());
        return new String(Base64.decode(dec, Base64.DEFAULT));
    }

今、私はこれを取得します:

javax.crypto.IllegalBlockSizeException: 入力は 96 バイト未満でなければなりません

4

2 に答える 2

0

別のプロジェクトに膨大な時間を費やした後、このアプリケーションに戻って問題を解決しました。

まず、SJCL/JSBN ライブラリが生成する秘密鍵 json は 16 進文字列です。そのため、文字列をバイト配列に変換する必要がありました。

BigInteger n = new BigInteger(Utils.hexStringToByteArray(nString));
BigInteger e = new BigInteger("10001", 16); // Public exponent

送信される暗号化されたデータも 16 進文字列です。

byte[] dec = cipher.doFinal(Utils.hexStringToByteArray(data));
return new String(dec, "UTF-8");

暗号は、バイト配列を平文として返します。

アルゴリズムを以下に示します。

Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding");

および hexStringToByteArray 関数:

public static byte[] hexStringToByteArray(String s) {
  int len = s.length();
  byte[] data = new byte[len/2];

  s = s.toUpperCase();
  for(int i = 0; i < len; i+=2){
    data[i/2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
  }

 return data;
}

public static String byteArrayToHexString(byte[] bytes) {
  char[] hexChars = new char[bytes.length*2];
  int v;

  for(int j=0; j < bytes.length; j++) {
    v = bytes[j] & 0xFF;
    hexChars[j*2] = hexArray[v>>>4];
    hexChars[j*2 + 1] = hexArray[v & 0x0F];
  }

  return new String(hexChars).toLowerCase();
}

当時、私は間違った場所を見ていて、BigInteger を base64 でコード化された文字列としてデコードしていました。

于 2015-02-16T16:25:24.580 に答える
0

RSA 秘密鍵のPrivateKey.getEncoded()は、 PKCS#1標準に従ってエンコードされた ASN.1 バイナリを返します。

于 2014-03-21T19:44:39.813 に答える