1

我正在尝试使用以下步骤在 java 中进行 api 调用:

  1. json编码
  2. RC4 加密
  3. base64 编码

我目前在 php 中使用相同的系统并且它工作正常:

$enc_request = base64_encode(openssl_encrypt(json_encode($request_params), "rc4", $this->_app_key));

但是当我在java中使用相同的系统时,结果却不如预期。这是我的代码:

//json encoding
JSONObject obj = new JSONObject();
obj.put("email", username);
obj.put("password", password);
obj.put("action", "login");

//function to encode base64
private String getBase64Encoded(String encryptedJsonString)
{
    byte[] encoded = Base64.encodeBase64(encryptedJsonString.getBytes());

    String encodedString = new String(encoded);

    return encodedString;
}

//function to encrypt in RC4
private String getRC4EncryptedString2(String string, String key) throws Exception
{
    Cipher cipher = Cipher.getInstance("RC4");
    SecretKeySpec rc4Key = new SecretKeySpec(key.getBytes(), "RC4");
    cipher.init(Cipher.ENCRYPT_MODE, rc4Key);

    byte[] cipherText = cipher.update(string.getBytes());

    return new String(cipherText);
}

我能够识别出问题,直到 RC4 加密没有返回与 php 版本相同的结果。

我已经为此奋斗了2天。我希望我没有错过任何愚蠢的事情,因为这应该是直截了当的。

谢谢

4

2 回答 2

1

您应该使用 a byte[]not aString来保存中间字节数组值。AString用于文本,而不是原始数据,并将尝试使用系统的默认字符集将字节解码为字符数据(至少,单参数String构造函数会)。与 相同String.getBytes()

cipherText直接从中返回getRC4EncryptedString2(),然后直接传递给getBase64Encoded(). 这些编码器在字节数组上运行是有原因的,而不是因为您可以通过在其间应用字符编码来混淆数据。

您传递给的密钥也是如此getRC4EncryptedString2()。在最低限度的使用String.getBytes("ISO-8859-1")或其他东西(假设您的密钥实际上是文本而不是另一个乱码字节数组)。的无参数版本getBytes()返回使用系统默认字符集编码的文本,不保证是您想要的。

这也适用于String您从 base 64 编码器返回的内容。我不知道您使用的是什么 base 64 编码器,但请确保为String构造函数指定字符集。很可能你会没事的,纯属巧合,但在转换为/从原始字节时,你应该始终指定一个字符集。String当然,这假设您的 base 64 编码器返回文本,而不是 0-63 范围内的字节。

String这里的一般要点是您不能只是从到来回转换byte[]。AString用于文本,它的表示形式byte[]取决于字符编码。

于 2013-08-16T05:46:01.313 回答
0

我可以使用以下代码来实现这一点。希望这可以帮助!

import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

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

import org.apache.commons.codec.DecoderException;
import org.bouncycastle.util.encoders.Hex;
import org.json.JSONException;
import org.json.JSONObject;

public class RC4Algo {

    public static void main(String args[])throws IOException, NoSuchAlgorithmException, DecoderException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, JSONException
    {
        decryptRC4();
    }

    static String decryptRC4() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, JSONException{

        //byte[] plainBytes = "testString".getBytes();

        //json encoding
        JSONObject obj = new JSONObject();
        obj.put("email", "username");
        obj.put("password", "password");
        obj.put("action", "login");

        byte [] plainBytes = obj.toString().getBytes();

        String hashedKey = hashedData("thisismysecretkey");

        //Generate a new key using KeyGenerator
        /*KeyGenerator rc4KeyGenerator = KeyGenerator.getInstance("RC4");
        SecretKey key = rc4KeyGenerator.generateKey();*/

        Key key = new SecretKeySpec(Hex.decode(hashedKey), "RC4");

        // Create Cipher instance and initialize it to encrytion mode
        Cipher cipher = Cipher.getInstance("RC4");  // Transformation of the algorithm
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] cipherBytes = cipher.doFinal(plainBytes);

        String encoded = encodeBase64(cipherBytes);

        String decoded = decodeBase64(encoded);

        // Reinitialize the Cipher to decryption mode
        cipher.init(Cipher.DECRYPT_MODE,key, cipher.getParameters());
        byte[] plainBytesDecrypted = cipher.doFinal(Hex.decode(decoded));

        System.out.println("Decrypted Data : "+new String(plainBytesDecrypted));
        return new String(plainBytesDecrypted);
    }

    static String decodeBase64(String encodedData){
        byte[] b = Base64.getDecoder().decode(encodedData);
        String decodedData = DatatypeConverter.printHexBinary(b);
        return decodedData;
    }

    static String encodeBase64(byte[] data){
        byte[] b = Base64.getEncoder().encode(data);
        String encodedData = new String(b);
        /*String encodedData = DatatypeConverter.printHexBinary(b);*/
        return encodedData;
    }

    static String hashedData(String key) throws NoSuchAlgorithmException{
        String password = key;

        MessageDigest md = MessageDigest.getInstance("MD5");
        md.update(password.getBytes());

        byte byteData[] = md.digest();

        //convert the byte to hex format method 1
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < byteData.length; i++) {
         sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
        }

        //convert the byte to hex format method 2
        StringBuffer hexString = new StringBuffer();
        for (int i=0;i<byteData.length;i++) {
            String hex=Integer.toHexString(0xff & byteData[i]);
            if(hex.length()==1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }

    }

输出:

在此处输入图像描述

于 2018-09-23T07:32:50.867 回答