Java 密码设置特定随机数不起作用
Java Cipher setting specific nonce is not workig
我需要加密 POST 请求中的参数(以便交换身份验证令牌)。
到目前为止,PHP 很好,我可以做到,请求成功。下面有PHP加密脚本(PHP密码不可修改)
<?php
$shared_secret = "dummy_secret";
// Genere user Json
$userJson = json_encode(array(
"external_id" => "30123134", //Required
"email" => "jperez@gmail.com",
"name" => "Jose",
"lastname" => "Perez"
));
// Generate nonce (initialization vector)
$nonce = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC) ,MCRYPT_RAND);
// Encrypt user Json to generate the encrypted form
$encryptedForm =mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $shared_secret, $userJson, MCRYPT_MODE_CBC, $nonce);
// Encode the encrypted form and the nonce
$encryptedForm = base64_encode($encryptedForm);
$nonce = base64_encode($nonce);
$body = json_encode(array("encryptedform" => $encryptedForm, "nonce" => $nonce));
?>
现在我正尝试对 Java 做同样的事情。不幸的是,我的实现一定有问题,因为 POST 请求 returns 401(未授权)。
public static EncryptedData encrypt(String plainText, String key) throws Exception {
// Generating IV.
byte[] iv = new byte[IV_SIZE];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(random.getSeed(IV_SIZE));
// Encrypt.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(), "AES"), ivParameterSpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
// Base64 encoding.
String nonce = DatatypeConverter.printBase64Binary(ivParameterSpec.getIV());
String encryptedFrom = DatatypeConverter.printBase64Binary(encrypted);
EncryptedData data = new EncryptedData(nonce, encryptedFrom);
return data;
}
java 版本有什么问题?
我找到了这个难题的解决方案,幸运的是我可以将 php 代码翻译成 java 等效代码:
public static ar.edu.ues21.menu.util.EncryptedData encrypt2(String key, String data) throws Exception {
ar.edu.ues21.menu.util.EncryptedData result = null;
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(128)), new ZeroBytePadding());
byte[] iv = new byte[16];
SecureRandom.getInstance("SHA1PRNG").nextBytes(iv);
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes("UTF-8")), iv);
cipher.init(true, ivAndKey);
byte[] input = data.getBytes("UTF-8");
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int cipherLength = cipher.processBytes(input, 0, input.length, cipherText, 0);
cipher.doFinal(cipherText, cipherLength);
result = new ar.edu.ues21.menu.util.EncryptedData(Base64.encodeBase64String(iv), Base64.encodeBase64String(cipherText));
return result;
}
但我很幸运,真正的问题是目标 API 没有任何关于令牌生成所需的加密类型的文档。
我需要加密 POST 请求中的参数(以便交换身份验证令牌)。 到目前为止,PHP 很好,我可以做到,请求成功。下面有PHP加密脚本(PHP密码不可修改)
<?php
$shared_secret = "dummy_secret";
// Genere user Json
$userJson = json_encode(array(
"external_id" => "30123134", //Required
"email" => "jperez@gmail.com",
"name" => "Jose",
"lastname" => "Perez"
));
// Generate nonce (initialization vector)
$nonce = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC) ,MCRYPT_RAND);
// Encrypt user Json to generate the encrypted form
$encryptedForm =mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $shared_secret, $userJson, MCRYPT_MODE_CBC, $nonce);
// Encode the encrypted form and the nonce
$encryptedForm = base64_encode($encryptedForm);
$nonce = base64_encode($nonce);
$body = json_encode(array("encryptedform" => $encryptedForm, "nonce" => $nonce));
?>
现在我正尝试对 Java 做同样的事情。不幸的是,我的实现一定有问题,因为 POST 请求 returns 401(未授权)。
public static EncryptedData encrypt(String plainText, String key) throws Exception {
// Generating IV.
byte[] iv = new byte[IV_SIZE];
SecureRandom random = new SecureRandom();
random.nextBytes(iv);
IvParameterSpec ivParameterSpec = new IvParameterSpec(random.getSeed(IV_SIZE));
// Encrypt.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes(), "AES"), ivParameterSpec);
byte[] encrypted = cipher.doFinal(plainText.getBytes());
// Base64 encoding.
String nonce = DatatypeConverter.printBase64Binary(ivParameterSpec.getIV());
String encryptedFrom = DatatypeConverter.printBase64Binary(encrypted);
EncryptedData data = new EncryptedData(nonce, encryptedFrom);
return data;
}
java 版本有什么问题?
我找到了这个难题的解决方案,幸运的是我可以将 php 代码翻译成 java 等效代码:
public static ar.edu.ues21.menu.util.EncryptedData encrypt2(String key, String data) throws Exception {
ar.edu.ues21.menu.util.EncryptedData result = null;
BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(128)), new ZeroBytePadding());
byte[] iv = new byte[16];
SecureRandom.getInstance("SHA1PRNG").nextBytes(iv);
CipherParameters ivAndKey = new ParametersWithIV(new KeyParameter(key.getBytes("UTF-8")), iv);
cipher.init(true, ivAndKey);
byte[] input = data.getBytes("UTF-8");
byte[] cipherText = new byte[cipher.getOutputSize(input.length)];
int cipherLength = cipher.processBytes(input, 0, input.length, cipherText, 0);
cipher.doFinal(cipherText, cipherLength);
result = new ar.edu.ues21.menu.util.EncryptedData(Base64.encodeBase64String(iv), Base64.encodeBase64String(cipherText));
return result;
}
但我很幸运,真正的问题是目标 API 没有任何关于令牌生成所需的加密类型的文档。