这是PHP 手册上的一个例子
<?php
$key = "this is a secret key";
$input = "Let us meet at 9 o'clock at the secret place.";$encrypted_data = mcrypt_ecb (MCRYPT_3DES, $key, $input, MCRYPT_ENCRYPT);
?>
上面的代码运行没问题,问题我现在需要加密使用的KEY长度为36,$key=941033C39066FBB8DFB9DC5306250ADCCA947F58D9756D56 
如下代码运行报错:<?php
$key="941033C39066FBB8DFB9DC5306250ADCCA947F58D9756D56";
$input = "Let us meet at 9 o'clock at the secret place.";$encrypted_data = mcrypt_ecb (MCRYPT_3DES, $key, $input, MCRYPT_ENCRYPT);
?>错误代码:
warning: mcrypt_generic_init() [function.mcrypt-generic-init]: Key size too large; supplied length: 36, max: 24也就是说KEY长度大于24时就不行了,该怎么办,有没有大侠提供解决方案,必定感激!

解决方案 »

  1.   

    不是都说了key的最大长度为24。这个函数是废弃,不应该用了,见mcrypt_generic()和mdecrypt_generic()的替代品。
      

  2.   

    用mdecrypt_generic,见手册上的例子:<?php
        /* Data */
        $key = 'this is a very long key, even too long for the cipher';
        $plain_text = 'very important data';    /* Open module, and create IV */
        $td = mcrypt_module_open('des', '', 'ecb', '');
        $key = substr($key, 0, mcrypt_enc_get_key_size($td));
        $iv_size = mcrypt_enc_get_iv_size($td);
        $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);    /* Initialize encryption handle */
        if (mcrypt_generic_init($td, $key, $iv) != -1) {        /* Encrypt data */
            $c_t = mcrypt_generic($td, $plain_text);
            mcrypt_generic_deinit($td);        /* Reinitialize buffers for decryption */
            mcrypt_generic_init($td, $key, $iv);
            $p_t = mdecrypt_generic($td, $c_t);        /* Clean up */
            mcrypt_generic_deinit($td);
            mcrypt_module_close($td);
        }    if (strncmp($p_t, $plain_text, strlen($plain_text)) == 0) {
            echo "ok\n";
        } else {
            echo "error\n";
        }
    ?>
      

  3.   

    和上面答的一样,但是给个详细的例子,加上一个加密类class AMPCrypt {
    private static function getKey(){
    return md5('exampleKey'); //自己定义的加密key
    }
    public static function encrypt($value){
    $td = mcrypt_module_open('tripledes', '', 'ecb', '');
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
    $key = substr(self::getKey(), 0, mcrypt_enc_get_key_size($td));
    mcrypt_generic_init($td, $key, $iv);
    $ret = base64_encode(mcrypt_generic($td, $value));
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    return $ret;
    }
    public static function dencrypt($value){
    $td = mcrypt_module_open('tripledes', '', 'ecb', '');
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
    $key = substr(self::getKey(), 0, mcrypt_enc_get_key_size($td));
    $key = substr(self::getKey(), 0, mcrypt_enc_get_key_size($td));
    mcrypt_generic_init($td, $key, $iv);
    $ret = trim(mdecrypt_generic($td, base64_decode($value))) ;
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);
    return $ret;
    }
    }
    $code = new AMPCrypt();
    $icode = $code->encrypt("123456");
    echo $icode;
    echo "<br>";
    $bcode = $code->dencrypt($icode);
    echo $bcode;
      

  4.   


    感谢楼上两位回复,现在问题的关键是,我是调用别人的Webservice, 对方是JAVA系统,
    给的KEY很长,超过24位楼上两位给的代码中有这样一句
    $key = substr($key, 0, mcrypt_enc_get_key_size($td));
    这明显是只是给的KEY的前24位
    这样的话,如果用两个KEY,只要前24位一样,后面给不给是无所谓了
    这样当然可以加密,但是对方通过SOAP收我的加密数据后,根本无法解密!
    因为KEY不一样,我只用了前24位,
      

  5.   

    附上对方给的JAVA代码示例,懂的给提提意见!import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.security.*;/**
     * @author guoxc
     * @create 2009-10-22
     */
    public class Cryptogram {

    private static byte[] defaultIV = {1,2,3,4,5,6,7,8}; private static byte chr2hex(String chr) {
    if (chr.equals("0")) {
    return 0x00;
    } else if (chr.equals("1")) {
    return 0x01;
    } else if (chr.equals("2")) {
    return 0x02;
    } else if (chr.equals("3")) {
    return 0x03;
    } else if (chr.equals("4")) {
    return 0x04;
    } else if (chr.equals("5")) {
    return 0x05;
    } else if (chr.equals("6")) {
    return 0x06;
    } else if (chr.equals("7")) {
    return 0x07;
    } else if (chr.equals("8")) {
    return 0x08;
    } else if (chr.equals("9")) {
    return 0x09;
    } else if (chr.equals("A")) {
    return 0x0a;
    } else if (chr.equals("B")) {
    return 0x0b;
    } else if (chr.equals("C")) {
    return 0x0c;
    } else if (chr.equals("D")) {
    return 0x0d;
    } else if (chr.equals("E")) {
    return 0x0e;
    } else if (chr.equals("F")) {
    return 0x0f;
    }
    return 0x00;
    } public static byte[] HexStringToByteArray(String s) {
    byte[] buf = new byte[s.length() / 2];
    for (int i = 0; i < buf.length; i++) {
    buf[i] = (byte) (chr2hex(s.substring(i * 2, i * 2 + 1)) * 0x10 + chr2hex(s
    .substring(i * 2 + 1, i * 2 + 2)));
    }
    System.out.println("hhhh:"+buf.toString());
    return buf;
    } /**
     * Encrypt the data by the key.
     * @param OriSource
     * @return strResult
     * @throws Exception
     */
    public static String encryptByKey(String OriSource, String key) throws Exception {

    String strResult = "";
    try {

    Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),
    "DESede"); IvParameterSpec ivspec = new IvParameterSpec(defaultIV);
    c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec); byte[] testSrc = OriSource.getBytes("utf-8");
    byte[] encoded = c3des.doFinal(testSrc);

    strResult = Base64Encrypt.getBASE64_byte(encoded);

    } catch (Exception e) {
    strResult="";
    System.out.println("Encrypt failure!!!");
    } return strResult;
    }

    /**
     * Decrypt the encrypted data with the key.
     * @param strData
     * @return strResult
     * @throws Exception
     */
    public static String decryptByKey(String encryptedData, String key) throws Exception {

    String strResult = "";
    try {

    Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),
    "DESede"); IvParameterSpec ivspec = new IvParameterSpec(defaultIV);
    c3des.init(Cipher.DECRYPT_MODE, myKey, ivspec); byte[] s= Base64Encrypt.getByteArrFromBase64(encryptedData);
    byte[] encoded = c3des.doFinal(s);
    strResult = new String(encoded,"utf-8");

    } catch (Exception e) {
    strResult="";
    System.out.println("Decrypt failure!!!");
    } return strResult;
    }

    /**
     * Decrypt the encrypted data with the key.
     * @param strData
     * @return strResult
     * @throws Exception
     */
    public static String getBase64HashString(String str) throws Exception{

    byte[] testSrc = str.getBytes();
    MessageDigest alga = MessageDigest.getInstance("SHA-1");
    alga.update(testSrc);
    byte[] digesta = alga.digest();
    return Base64Encrypt.getBASE64_byte(digesta);
    }


    /**
     * Decrypt the encrypted data with the key.
     * @param strData
     * @return strResult
     * @throws Exception
     */
    public static String getAuthenicator(String sourceStr,String key) throws Exception{

    String strResult = "";
    try {

    Cipher c3des = Cipher.getInstance("DESede/CBC/PKCS5Padding");
    SecretKeySpec myKey = new SecretKeySpec(HexStringToByteArray(key),
    "DESede"); IvParameterSpec ivspec = new IvParameterSpec(defaultIV);
    c3des.init(Cipher.ENCRYPT_MODE, myKey, ivspec);


    byte[] testSrc = sourceStr.getBytes();
    MessageDigest alga = MessageDigest.getInstance("SHA-1");
    alga.update(testSrc);
    byte[] digesta = alga.digest(); byte[] encoded = c3des.doFinal(digesta);
    strResult = Base64Encrypt.getBASE64_byte(encoded);

    } catch (Exception e) {
    strResult="";
    System.out.println("Decrypt failure!!!" + e.getMessage());
    } return strResult;
    }
    public static void main(String args[]) throws Exception {
    String SysID = "0005郭";
    String TimeStamp = "2009-10-22 13:15:20";
    String ReturnURL = "http://vnet.cn/passportinterface/test2.aspx郭";
    String Key = "941033C39066FBB8DFB9DC5306250ADCCA947F58D9756D56";

    try{

    //Get Digest.
    String Digest = getBase64HashString(SysID + TimeStamp + ReturnURL);
    System.out.println("The Base64HashString data :" + Digest);

    //Get 3DES data.
    String EncryptStr = encryptByKey("hello",Key);
    //String EncryptStr = "你好";

    System.out.println("The Encrypted data :" + EncryptStr);

    //String DecryptStr = decryptByKey("EPjZO26ZZBk=",Key);

    //System.out.println("The Decrypted data :" + DecryptStr);


    String A = "guo";
    //A = getAuthenicator(A,Key);
    //System.out.print("The Encrypted data :" + A);

    }
    catch(Exception Ex){
    Ex.printStackTrace();
    }
    }
    }
      

  6.   

    看了半天,也没搞明白楼主说的“KEY长度大于24时就不行了”具体是指什么。那个 key,是应该以“字符串”的方式提供吗?看楼主给的代码,那个 941033C39066FBB8DFB9DC5306250ADCCA947F58D9756D56 很像是 hex 表达形式,如果转换成对应的字节数组,正好是 24 个字节,不妨试试 :)
      

  7.   

    楼上的给了很好的思路,
    可是int mcrypt_generic_init ( resource $td , string $key , string $iv )这里需要的key是个字符串啊
    我传个字节数组过去?941033C39066FBB8DFB9DC5306250ADCCA947F58D9756D56 
    这个怎么转换为字节数组啊
      

  8.   

    试试这个嘛
    $key="\x94\x10\x33\xC3\x90\x66\xFB\xB8\xDF\xB9\xDC\x53\x06\x25\x0A\xDC\xCA\x94\x7F\x58\xD9\x75\x6D\x56";
    $input = "Let us meet at 9 o'clock at the secret place.";
    $encrypted_data = mcrypt_ecb (MCRYPT_3DES, $key, $input, MCRYPT_ENCRYPT);
      

  9.   

    所谓“字节数组”,其实是沿用 Java 的说法,你给的那段 Java 程序里不是也有个 HexStringToByteArray() 嘛。在 PHP 里,string 名为“字符串”,只是习惯说法而已,一般用来表示“字符”的串,而从本质上说,它应该叫“字节串”,可以用来保存任意的“字节”,甚至包括零值的字节 "\x00"。
      

  10.   

    +++按你给出的java代码,那个key就是转换后的16进制字符
      

  11.   

    941033C39066FBB8DFB9DC5306250ADCCA947F58D9756D56
    密钥长度为48,
    用pack("H48", "941033C39066FBB8DFB9DC5306250ADCCA947F58D9756D56")处理就得到24位的密钥了。
    另外,为了保证处理一致,请参照对方是用何种方式处理加密文件的,
    我知道的有三种,pkcs5,pkcs7,无处理
      

  12.   

    确实只有24位,用pack的话,必须得是16进制字符串如果是任意字符串呢?
      

  13.   

    $key = "这里就是随意长度唯一的字符串1";//从外部能获取到的唯一key
    $key = md5 ( $key ) . '1234567890123456';//构造48位key
    $key = base64_encode ( pack ( 'H48', $key ) );//构造最终的key
    $iv = base64_encode ( pack ( 'H16', md5 ( "这里就是随意长度唯一的字符串2" ) ) );我觉得这样可以解决唯一性。
      

  14.   

    关于java和php 3des加密 的问题,我看了你去年的帖子,是电信的接口吗?。。现在遇到和你一样的问题,困扰,如果你解决了 可以告知一下如何解决的吗?
    有代码的话不胜感激 [email protected]还有php 和java的sha1 加密出来不一样,如何解决的?