我在开发中需要对字符串进行DES加密
在本机上测试时对任何字符串加密解密都没有问题
但是一旦使用了Soket网络传输以后解密出现问题,是密文长度不够造成的
我的加密解密程序如下:
public   class   DesEncrypt   {
      Key   key;      /**
        *   根据参数生成KEY
        *   @param   strKey
        */
        public   void   getKey(String   strKey)   {
          try   {
              KeyGenerator   _generator   =   KeyGenerator.getInstance("DES");
              _generator.init(new   SecureRandom(strKey.getBytes()));
              this.key   =   _generator.generateKey();
              _generator   =   null;
          }   catch   (Exception   e)   {
              e.printStackTrace();
          }
      }      /**
        *   加密String明文输入,String密文输出
        *   @param   strMing
        *   @return
        */
      public   String   getEncString(String   strMing)   {
          byte[]   byteMi   =   null;
          byte[]   byteMing   =   null;
          String   strMi   =   "";
          Base64 base64en = new Base64();
          try   {
              byteMing   =   strMing.getBytes("UTF-8");
              byteMi   =   this.getEncCode(byteMing);
              strMi   = base64en.encode(byteMi);          }   catch   (Exception   e)   {
              e.printStackTrace();
          }   finally   {
              base64en   =   null;
              byteMing   =   null;
              byteMi   =   null;
          }
          return   strMi;
      }      /**
        *   解密   以String密文输入,String明文输出
        *   @param   strMi
        *   @return
        */
      public   String   getDesString(String   strMi)   {
          Base64   base64De   =   new   Base64();
          byte[]   byteMing   =   null;
          byte[]   byteMi   =   null;
          String   strMing   =   "";
          try   {
           byteMi=base64De.decode(strMi);
              byteMing   =   this.getDesCode(byteMi);
              strMing   =   new   String(byteMing,   "UTF-8");
          }   catch   (Exception   e)   {
              e.printStackTrace();
          }   finally   {
              base64De   =   null;
              byteMing   =   null;
              byteMi   =   null;
          }
          return   strMing;
      }      /**
        *   加密以byte[]明文输入,byte[]密文输出
        *   @param   byteS
        *   @return
        */
      private   byte[]   getEncCode(byte[]   byteS)   {
          byte[]   byteFina   =   null;
          Cipher   cipher;
          try   {
              cipher   =   Cipher.getInstance("DES"); 
              cipher.init(Cipher.ENCRYPT_MODE,   key);
              byteFina   =   cipher.doFinal(byteS);
          }   catch   (Exception   e)   {
              e.printStackTrace();
          }   finally   {
              cipher   =   null;
          }
          return   byteFina;
      }      /**
        *   解密以byte[]密文输入,以byte[]明文输出
        *   @param   byteD
        *   @return
        */
      private   byte[]   getDesCode(byte[]   byteD)   {
          Cipher   cipher;
          byte[]   byteFina   =   null;
          try   {
              cipher   =   Cipher.getInstance("DES"); 
              cipher.init(Cipher.DECRYPT_MODE,   key);
              byteFina   =   cipher.doFinal(byteD);
          }   catch   (Exception   e)   {
              e.printStackTrace();
          }   finally   {
              cipher   =   null;
          }
          return   byteFina;
      }      public   static   void   main(String   args[])   {
          DesEncrypt   des=new   DesEncrypt();//实例化一个对像
          des.getKey("asdefd");//生成密匙          String   strEnc   =   des.getEncString("ceshi测试");//加密字符串,返回String的密文
          System.out.println("加密文:"+strEnc);
          String   strDes   =   des.getDesString(strEnc);//把String   类型的密文解密
          System.out.println("解密文:"+strDes);
      }大家帮忙看看 很急的问题

解决方案 »

  1.   

    不知道你的Base64是哪里来的。我用BASE64Decoder来做的BTW,我觉得你的问题不是encrypt/decrypt中出的问题,而是Socket传输出的问题。
    而最关键的部分你没有贴上来socket传输后,加解密采用了相同的key吗?
      

  2.   

    密文长度不够,说明你在用 Socket 接收的时候没等传送完就终止了。
      

  3.   

    不是的socket传输没有问题,因为我是用的String进行的传输,所以先将加密后的byte[] 转换成了String在接收端再将String转换为了byte[]问题就是在这个时候出的
    两端使用的Key也是相同的,现在是有些解密没有问题,有些就不行了
    报的错误都是
    Input length must be multiple of 8 when decrypting with padded cipher
      

  4.   

    我在进行文件传输的时候采用的是按行传输下面是发送代码:
    File f = new File(filePath);
    fr = new FileReader(f);
    br = new BufferedReader(fr);
    ps.println(file); //其中的file 是文件的名称
    String str;
    while ((str = br.readLine()) != null) {
       String mi = des.getEncString(str);
       ps.println(mi);
    }
    br.close();
    fr.close();下面是接收程序:
    private Socket socket ;
    private BufferedReader bf;
    private PrintStream ps;
    private CesConstant ces;
    private DesEncrypt des;
    ……
    ……
    bf = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    filename = bf.readLine();
    if (filename == null) {
        continue;
     }
    file = new File(receivePath+ filename);
    fw = new FileWriter(file);
    bw = new BufferedWriter(fw);
    pw = new PrintWriter(bw);
    String str;
    while (( str=bf.readLine()) != null) {
    String ming = des.getDesString(str);
    pw.println(ming);
    }
    ……
    ……
    我觉得关键在于将String转换为byte[]时的补位问题,但是没怎么接触过DES所以不知道怎么解决,请大家帮帮忙,真的很急
      

  5.   

    哈,这种东西怎么可以随便就用ps.println(mi);或者readLine来做呢
    readLine在读到一个字符串后,通过println发出去,会在最后加上一个\r\s,而这个死符串本身可能就在末尾,也就没有\r\n,或者只有\n这样的写法极其危险。你应该直接发送byte数组,而不要发String
      

  6.   

    我知道,但是这是一个时时监听的发送程序,不止是发一个文件,所以我必须先从流中读出文件文件名称,如果使用byte数组发送的话,就没有办法截取到文件名了,而且发送采用了握手协议发送完一个文件后等到收到接收端的确认信息,才能继续发送下一个文件,如果使用byte做得话连确认信息也不好判断了
      

  7.   

    这样的程序,要求传输数据的准确性更高
    一般我们自己组建tcp包会这样
    名称      类型   长度(字节)  内容
    NameLen   String  10           文件名长度
    Name      String  NameLen      文件名
    TxtLen    String  10           文件长度
    Text      byte[]  TxtLen       文件内容这样你一块一块解析,什么都可以得到
      

  8.   

    你最终要明白,socket传输的都是byte流,你按照一定长度来读取byte流,再组合就可以了。按上面的说法
    你先读取10个byte,然后组成String,trim一下,然后用long txtLen=Long.parseLong得到long值。这个就是下面内容的长度。在byte buf[]=new byte[txtLen];is.read(buf);String txt=new String(buf);这样就得到完整的text了。自己慢慢想一下,不是很难。和java无关,只是一个逻辑处理,或者说数学问题
      

  9.   

    我按照以行为单位传输的话每条String应该不会存在\r,\r\n 或者是\n之内的东西,所以可以把加密后所有的这些字符去掉,我测试过了这样也不会影响解密呵呵 还是谢谢你了