我正在尝试使用以下步骤在java中进行api调用:
我目前在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天了。我希望我没有错过任何愚蠢的事情,因为这应该是直截了当的。
由于
答案 0 :(得分:1)
您应该使用byte[]
而不是String
来保存中间字节数组值。 String
用于文本,而不是原始数据,并将尝试使用系统的默认字符集(至少单参数String
构造函数)将字节解码为字符数据。与String.getBytes()
相同。
直接从cipherText
返回getRC4EncryptedString2()
,然后直接将其传递给getBase64Encoded()
。这些编码器在字节数组上运行是有原因的,原因是不,因此您可以通过在其间应用字符编码来使数据混乱。
您传递给getRC4EncryptedString2()
的密钥也是如此。至少使用String.getBytes("ISO-8859-1")
或其他东西(假设你的密钥实际上是文本而不是另一个乱码字节数组)。无参数版本的getBytes()
返回使用系统默认字符集编码的文本,但不保证是您想要的。
这也适用于您从base 64编码器返回的String
。我不知道您使用的是哪种base 64编码器,但请确保为String
构造函数指定字符集。很可能你会很好,纯粹是巧合,但你应该总是在转换为/ String
和原始字节时指定一个字符集。当然,假设您的base 64编码器返回文本,而不是0-63范围内的字节。
这里的一般要点是,您不能只从String
来回转换为byte[]
。 String
用于文本,而byte[]
表示取决于字符编码。
答案 1 :(得分: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();
}
}
输出: