2016-06-01 19 views
0

サードパーティのAPIを呼び出すためには、UNIXタイムスタンプを暗号化する必要があります。その文書では、彼らは私が使用しなければならない指定:PHPでタイムスタンプを暗号化し、Javaで解読する

  • をアルゴリズム:128ビットAES、モード:CBC
  • パディング:PKCS5Padding
  • 初期化ベクター: "0000000000000000"

そして、彼らは与えます例:

クライアントは、タイムスタンプ1464284796、初期化ベクトル '0000000000000000 'と彼らも暗号化されたタイムスタンプを生成するために、サンプルコードを与えるbase64でauth_token 6BH3hg1cqQJOK6sG8gw7Xw ==で

を結果として秘密鍵b35901b480ca658c8be4341eefe21a80、問題は、彼らは、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; 
    } 
} 

使用法:PHPで

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); 

私の試み:

[[email protected] ~]$ 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'); 



[[email protected] ~]$ php -f api.php 
UXRvTOIPiiYfBUoDFRaC5w== 

正直なところ、私は自分のやっていること、特にJAVAで何をしているのか分かりません。私はサンプルコードをどのように実行するか分からない。

注:クライアントは、タイムスタンプ 1464284796、初期化ベクトル使用して、その実装をテストする必要があります。「0000000000000000」を

UPDATE

サードパーティは、そのサンプルの改正で私たちに手を差し伸べそして、 base64でauth_token ZnNmKbcdxRrYTDBgQKI9aQ ==その結果 秘密鍵b35901b480ca658c8be4341eefe21a80

$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; 
} 
+0

準備Javaコードを実行するためのシステムコールは、代替だろうか?これは答えを得ることができ、PHPですべてのものを実装するより簡単かもしれません。 –

答えて

1

数字は単なる10進文字列ではありません。それらをバイナリ表現にエンコードする必要があります。これはpackで行うことができます。 Longs.toByteArray(timestamp)は、64ビットのビッグエンディアン表記のタイムスタンプをエンコードし、あなたがこのエンコーディングと一致する必要があるので:

$ts = "\0\0\0\0" . pack('N', '1464284796'); 
echo openssl_encrypt($ts, 'AES-128-CBC', hex2bin('b35901b480ca658c8be4341eefe21a80'), 
     null, '0000000000000000')); 
+0

'6BH3hg1cqQJOK6sG8gw7Xw =='を出力します!どうもありがとうございます!!! –

0

は、あなたが使用しているJavaのAPIのを見てください:

ソリューションはpack機能をrevomeすることです。彼らは実際に16進文字列を期待していますか?それはJavaでは非常に珍しいことです。

ここにあなたのコードが「initialVector.getBytesは()」APIは、バイト配列ではなく、16進数文字列の壊れたバイト配列表現を望んでいることを示唆している、と言う:)

理由は、PHPやJSのコードことが多いですこれらの言語でバイト配列をサポートしていないということです(少なくとも伝統的に、現代のJSにはバイト配列が存在します)。

関連する問題