- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要加密 unix 时间戳才能调用第三方 API。在他们的文档中,他们指定我必须使用:
然后他们举了一个例子:
Clients must test their implementation using the timestamp 1464284796, the initialization vector: '0000000000000000' and the secret key b35901b480ca658c8be4341eefe21a80 which resulting in the base64 auth_token 6BH3hg1cqQJOK6sG8gw7Xw==
他们甚至提供了生成加密时间戳的示例代码,问题是他们使用 Java 而我们使用 PHP。我在 PHP 中尝试的所有内容与预期输出不匹配,即 6BH3hg1cqQJOK6sG8gw7Xw== 。
这是他们的 Java 示例:
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import com.google.common.primitives.Longs;
class Encryptor {
private String initialVector;
private static final String TRANFORMATION = "AES/CBC/PKCS5Padding";
private static final String ALGORITHM = "AES";
String encrypt(SecretKeySpec key, long timestamp) throws Exception {
byte[] encryptedBytes =
getEncryptingCipher(key).doFinal(Longs.toByteArray(timestamp));
return Base64.encodeBase64String(encryptedBytes);
}
private Cipher getEncryptingCipher(SecretKeySpec key) throws
NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException,
InvalidKeyException,
InvalidAlgorithmParameterException {
Cipher encryptingCipher = Cipher.getInstance(TRANFORMATION);
encryptingCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(initialVector.getBytes()));
return encryptingCipher;
}
private SecretKeySpec getSecretKeySpec(String key) throws DecoderException {
byte[] keyBytes = Hex.decodeHex(key.toCharArray());
return new SecretKeySpec(keyBytes, ALGORITHM);
}
void setInitialVector(String initialVector) {
this.initialVector = initialVector;
}
}
用法:
Encryptor encryptor = new Encryptor();
encryptor.setInitialVector("0000000000000000");
//Expensive operation so only performed once, re-use the key spec instance
SecretKeySpec keySpec =
encryptor.getSecretKeySpec("b35901b480ca658c8be4341eefe21a80");
long timestamp = System.currentTimeMillis() / 1000;
String authToken = encryptor.encrypt(keySpec, timestamp);
我在 PHP 中的尝试:
[acool@acool ~]$ php -a
Interactive shell
php > echo openssl_encrypt( '1464284796','AES-128-CBC','b35901b480ca658c8be4341eefe21a80',null,'0000000000000000');
8PM7LQM7Xmb2NCBE3Hp00g==
php >
然后:
<?php
function encrypt($message, $initialVector, $secretKey) {
return base64_encode(
mcrypt_encrypt(
MCRYPT_RIJNDAEL_128,
$secretKey,
$message,
MCRYPT_MODE_CBC,
$initialVector
)
);
}
function encrypt_something($input)
{
$size = mcrypt_get_block_size('rijndael-128', 'cbc');
$input = pkcs5_pad($input, $size);
$key = 'b35901b480ca658c8be4341eefe21a80';
$td = mcrypt_module_open('rijndael-128', '', 'cbc', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, '0000000000000000');
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
function pkcs5_pad ($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function pkcs5_unpad($text)
{
$pad = ord($text{strlen($text)-1});
if ($pad > strlen($text)) return false;
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
return substr($text, 0, -1 * $pad);
}
echo encrypt_something('1464284796');
//echo encrypt('1464284796','0000000000000000','b35901b480ca658c8be4341eefe21a80');
[acool@acool ~]$ php -f api.php
UXRvTOIPiiYfBUoDFRaC5w==
老实说,我不太清楚自己在做什么,特别是在 JAVA 中。我什至不知道如何运行示例代码。
更新
第三方联系我们修改了他们的样本:
Note: clients must test their implementation using the timestamp 1464284796, the initialization vector: '0000000000000000' and the secret key b35901b480ca658c8be4341eefe21a80 which resulting in the base64 auth_token ZnNmKbcdxRrYTDBgQKI9aQ==
解决办法是修改pack
函数:
$ts = '1464284796';
$key = "b35901b480ca658c8be4341eefe21a80";
$authToken = openssl_encrypt( $ts, 'AES-128-CBC', hextobin($key), null, '0000000000000000');
function hextobin($hexstr)
{
$n = strlen($hexstr);
$sbin ="";
$i =0;
while($i<$n)
{
$a =substr($hexstr,$i,2);
$c = pack("H*",$a);
if ($i==0){$sbin=$c;}
else {$sbin.=$c;}
$i+=2;
}
return $sbin;
}
最佳答案
数字不仅仅是十进制字符串。您必须将它们编码为二进制表示形式。这可以通过 pack
来完成。由于 Longs.toByteArray(timestamp)
以 64 位大端表示法对时间戳进行编码,因此您必须匹配以下编码:
$ts = "\0\0\0\0" . pack('N', '1464284796');
echo openssl_encrypt( $ts, 'AES-128-CBC', hex2bin('b35901b480ca658c8be4341eefe21a80'),
null, '0000000000000000'));
关于java - 在 PHP 中加密时间戳并在 Java 中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37559237/
给定一个带有多个 date_time 戳的字符串,我想 提取第一个戳及其前面的文本 候选字符串可以有一个或多个时间戳 后续的 date_time 戳记将被 sep="-" 隔开 后续date_time
是否可以合并从相机拍摄的文本和照片?我想在照片上标记日期和时间,但我在 Google 上找不到任何内容。 最佳答案 使用下面的代码来实现你所需要的。 Bitmap src = Bitm
有没有办法通过 Graph API 戳另一个用户?基于this post ,并使用 Graph Explorer ,我发布到“/USERID/pokes”,我已经授予它(Graph API 应用程序和
我有两个向左浮动的元素。一个是 body 的第一个 child ,另一个是容器的第一个 child ,容器是 body 的第二个 child 。 ...
我是一名优秀的程序员,十分优秀!