2

データをサードパーティのアプリケーションに渡す暗号化システムに取り組んでいます。暗号化はJavaで行われ、復号化はPHPで行われます。何度か試みましたが、暗号化された文字列をPHPアプリケーションで開くことができません。

テストの目的で、データも暗号化するPHPスクリプトを作成したので、JavaとPHPで暗号化された文字列を比較できました。結果は21番目の文字まで一致し、その後は異なります。これは私が持っているものです:

// Java - Encrypt
private String EncryptAES(String text,String key) throws Exception
    {
      SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");

      // Instantiate the cipher
      Cipher cipher = Cipher.getInstance("AES");

      cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
      byte[] encrypted = cipher.doFinal(text.getBytes());

      String encrypttext = new BASE64Encoder().encode(encrypted);

      return encrypttext;
    }

RESULT: TeUZAFxoFoQy/roPm5tXyPzJP/TLAwR1aIGn2xHbZpsbY1qrKwXfO+F/DAqmeTwB0b8e6dsSM+Yy0zrQt22E2Q== 

// PHP - Encrypt
<?php

$encrypt =  $crypt = openssl_encrypt($toCrypt,"AES256","key-32-char-long");
echo $encrypt; 

?>

RESULT: TeUZAFxoFoQy/roPm5tXyC05wta1Z5YOXcq4OtgFoSbfVi/bHAuD6B5tDthT8EcGXQir08UAx0QvcqRJ2fJmbQ==

文字列の一部が一致しているため、明らかに何かが正しく行われていますが、残りが一致していないため、明らかにすべてが正しいわけではありません。また、PHPでJava文字列を復号化しようとしても、何も起こりません。

// PHP - Decrypt
<?php
$toDecrypt = "TeUZAFxoFoQy/roPm5tXyPzJP/TLAwR1aIGn2xHbZpsbY1qrKwXfO+F/DAqmeTwB0b8e6dsSM+Yy0zrQt22E2Q==";
$decrypt = openssl_decrypt($toDecrypt,"AES256","<key-32-char-long>");
echo $decrypt;

?>

RESULT: <nothing>

誰かが何が起こっているのか考えていますか?

4

5 に答える 5

3

暗号化された文字列は両方とも同じ文字で始まるため、一方にECBを使用し、もう一方にCBCを使用しているように見えます。

于 2012-05-04T15:32:35.877 に答える
1

いくつかの意見:

  • キーサイズはJavaプログラムでは明示的ではありません
  • 両方のプログラムのブロック暗号動作モードを確認しましたか?CBC、ECB、OFBなど...?暗号化されたデータを渡すためにIVが必要な場合もあります。
  • 最後のアイデア:JavaおよびPHPプログラムで使用されるパディングは何ですか?

このドキュメントはあなたを助けることができます:あなたはすべての有効な組み合わせ暗号/ブロック暗号モード/パディングモード/キーサイズを持っています。

于 2012-05-04T14:50:21.043 に答える
1

これはどうですか(PHP内で復号化するため):

$toDecrypt = "TeUZAFxoFoQy/roPm5tXyPzJP/TLAwR1aIGn2xHbZpsbY1qrKwXfO+F/DAqmeTwB0b8e6dsSM+Yy0zrQt22E2Q==";
$decrypt = openssl_decrypt(base64_decode($toDecrypt),"AES256","key-32-char-long");
echo $decrypt;

base64でデコードされた文字列を復号化する必要があり、復号化する場合は呼び出さopenssl_decryptないでくださいopenssl_encrypt:-)

于 2012-05-04T14:58:51.300 に答える
1

JavaでgetBytesを使用しています

代わりに、getBytes(Charset)メソッドを使用して、PHPで使用されているものと同じキーとプレーンテキストのエンコーディングを確保してください

(両方のバイト配列をダンプし、先に進む前にそれらが一致するかどうかを確認してください)

于 2012-05-04T14:59:06.057 に答える
0

私はこれを機能させました。やるべきことは、パディングする前に文字列をUTF-8としてエンコードしてから、暗号化するためにバイト配列を送信することです。UTF-8は、アクセント付き文字を2つの16進バイトc3 xxとして表すため、エンコードする必要のある文字が含まれている場合、変換される文字列は長くなります。ところで、c3文字は「A」で、上部に「〜」が付いているため、復号化にこれらの奇数文字が表示される場合は、復号化を再コーディングしていません。

import java.security.NoSuchAlgorithmException;

インポートjavax.crypto.Cipher; インポートjavax.crypto.NoSuchPaddingException; インポートjavax.crypto.spec.IvParameterSpec; インポートjavax.crypto.spec.SecretKeySpec;

import android.util.Log;

パブリッククラスMCrypt{

private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
private String iv = "cant hear you";
private String SecretKey = "top secret";

public MCrypt()
{
    ivspec = new IvParameterSpec(iv.getBytes());
    keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");                        
    try {            
        cipher = Cipher.getInstance("AES/CBC/NoPadding");
    } catch (NoSuchAlgorithmException e) {
         e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        e.printStackTrace();
    }
}

public byte[] encrypt(String text) throws Exception{
    if(text == null || text.length() == 0) throw new Exception("Empty string");

    byte[] bs = text.getBytes("UTF-8");

    byte[] toEncrypt = padBytes(bs);
    byte[] encrypted = null;
    try {
        cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
        encrypted = cipher.doFinal(toEncrypt);
    } catch (Exception e){                       
            throw new Exception("[encrypt] " + e.getMessage());
    }
    return encrypted;
}

public byte[] decrypt(String code) throws Exception{
    if(code == null || code.length() == 0)  throw new Exception("Empty string");        
    byte[] decrypted = null;
    try {
        cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);                
        decrypted = cipher.doFinal(hexToBytes(code));
    } catch (Exception e){
        throw new Exception("[decrypt] " + e.getMessage());
    }
    return decrypted;
}



    public static String bytesToHex(byte[] data){
        if (data==null){
            return null;
        }            
        int len = data.length;
        String str = "";
        for (int i=0; i<len; i++) {
            if ((data[i]&0xFF)<16)
                    str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
            else
                    str = str + java.lang.Integer.toHexString(data[i]&0xFF);
        }
        return str;
    }


    public static byte[] hexToBytes(String str) {
            if (str==null) {
                    return null;
            } else if (str.length() < 2) {
                    return null;
            } else {
                    int len = str.length() / 2;
                    byte[] buffer = new byte[len];
                    for (int i=0; i<len; i++) {
                            buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
                    }
                    return buffer;
            }
    }



    private static byte[] padBytes(byte[] source){
        char paddingChar = ' ';
        int size = 16;
        int x = source.length % size;
        int padLength = size - x;
        int bufferLength = source.length + padLength;
        byte[] ret = new byte[bufferLength];
        int i = 0;
        for ( ; i < source.length; i++){
            ret[i] = source[i];
        }
        for ( ; i < bufferLength; i++){
            ret[i] = (byte)paddingChar;
        }

        return ret;
    }
} // class close

pHp側も同様です...(ここにpHpコードを入力する方法がわかりません!!!!

class MCrypt
{               
private $iv =  'adfdadfgfd'; #Same as in JAVA
private $key = 'adfadfdfdafadfa'; #Same as in JAVA


function __construct()
{
}

function encrypt($str) {
  $iv = $this->iv;
  $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);
  mcrypt_generic_init($td, $this->key, $iv);
  $s = padString(utf8_encode($str));
  $encrypted = mcrypt_generic($td, $s);
    //echo $encrypted;
  mcrypt_generic_deinit($td);
  mcrypt_module_close($td);
  return bin2hex($encrypted);
}

function decrypt($code) {
  $code = $this->hex2bin($code);
  $iv = $this->iv;
  $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv);
  mcrypt_generic_init($td, $this->key, $iv);
  $decrypted = mdecrypt_generic($td, $code);
  mcrypt_generic_deinit($td);
  mcrypt_module_close($td);
  return (trim(utf8_decode($decrypted)));
}

protected function hex2bin($hexdata) {
  $bindata = '';
  for ($i = 0; $i < strlen($hexdata); $i += 2) {
    $bindata .= chr(hexdec(substr($hexdata, $i, 2)));
  }
  return $bindata;
}   
}

それだけです、本当に簡単です...ちなみに、自分でパディングを行う場合は、方法がパディングであるかノーパディングであるかは関係ありません。

于 2014-01-05T16:06:11.460 に答える