Delphi, C#, Java 三者兼容的DES字节流加密/解密

来源:http://hi.baidu.com/spacetimer/item/65d5a13f4af069be124b1479
网络传数据时一般要经过加密, 较简单的DES对称加密(CRC模式,PKCS7)

==================================================================================
C#(客户端):

using System.Security.Cryptography;
...
/// <summary>
/// 进行DES加密。
/// </summary>
/// <param name="pToEncrypt">要加密的字节数组。</param>
/// <param name="sKey">密钥,且必须为8位。</param>
/// <returns>以Base64格式返回的加密字符串。</returns>
public static string Encrypt(byte[] bEncrypt, string sKey)
{
//return ToBase64(bEncrypt);

using (DESCryptoServiceProvider des = new DESCryptoServiceProvider()) //默认为crc,pkcs7
{
//byte[] inputByteArray = Encoding.UTF8.GetBytes(pToEncrypt);
des.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
des.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
try
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bEncrypt, 0, bEncrypt.Length);
cs.FlushFinalBlock();
cs.Close();
}
}
catch
{
return "";
}
string str = Convert.ToBase64String(ms.ToArray());
ms.Close();
return str;
}
}
注意这里直接用key当做VI向量,并且默认的padding策略为PKCS7

===================================================================================
Java Web服务端:


package com.spt.util;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
...

public class DESTool {

// 采用的是DES算法
private SecretKey secretKey;// 密钥
private IvParameterSpec iv;// 偏移量
private Cipher decryptCipher;// 解密对象

/*
* strKey必须是8位长度的字符串,即64bit。
*/
public DESTool(String strKey) {
try {
// 指定算法产生解密对象
decryptCipher = Cipher.getInstance("DES/CBC/PKCS5Padding"); //选择模式和填充方式,与.NET对应
// 由用户密钥产生系统密钥
secretKey = SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec(strKey.getBytes("UTF-8")));
// 产生偏移量
iv = new IvParameterSpec(strKey.getBytes("UTF-8"));
// 加载解密对象
decryptCipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
}

/**
* 解密.net平台上C#加密过的字节数组
*
* @param arrB 待解密的字节数组
* @return 解密后的字节数组
* @throws IllegalBlockSizeException
* @throws BadPaddingException
*/
public byte[] decrypt(byte[] arrB) throws IllegalBlockSizeException, BadPaddingException {
return decryptCipher.doFinal(arrB);
}
}

==================================================================================
Delphi 客户端相应的DES加密
网上流传的一些des算法没有crc预处理和设置iv向量,因此为了上面的web服务端能够解密需要手工做些预处理

unit EncodingUtil;

interface

uses
SysUtils, Classes, Types, EncdDecd, LbCipher;

//输入首地址和长度、key串返回encrypted block
function DESEncrypt(pInData : PByte; dataLen : Integer; keyStr : string) : TByteDynArray;

implementation

function DESEncrypt(pInData : PByte; dataLen : Integer; keyStr : string) : TByteDynArray;
var
temp, res, byteStr, arrStr: string;
poschar : char;
Encrypt : boolean;
key : TKey64;
i, j, len, strLen, posnum, resLen, index : integer;
Context : TDESContext;
block, iv: TDESBlock;
lastByte, curByte : Byte;
begin
resLen := dataLen + 1;
if resLen mod 8 <> 0 then
resLen := resLen + (8 - (resLen mod );
SetLength(Result, resLen);
index := 0;

Encrypt := true;
strLen := Length(keyStr);

//iv也默认和key一样
for i:=0 to 7 do
begin
if i > (strLen-1) then
begin
key[i] := 0;
iv[i]:= 0
end
else
begin
key[i] := byte(keyStr[i+1]);
iv[i] := key[i];
end;
end;

InitEncryptDES(Key, Context, Encrypt);
len := dataLen;
lastByte := Byte(8 - (dataLen mod );

posnum := 0;
for i:=0 to len do
begin
if (i = len) then
curByte := lastByte
else
curByte := (PByte(longint(pInData) + i))^;
block[posnum] := curByte;
posnum := posnum +1;
if posnum = 8 then
begin
EncryptDESCBC(Context, IV, block);   //block modified
for j:= 0 to 7 do
begin
Result[index] := block[j];
index := index + 1;
end;
iv := block;
posnum := 0;
end;
end;

if  posnum <> 0 then
begin
for i := posnum to 7 do
begin
block[i] := lastByte;
end;
EncryptDESCBC(Context, IV, Block);
for j:= 0 to 7 do
begin
Result[index] := block[j];
index := index + 1;
end;
posnum := 0;
end;

{
if index <> resLen then
ShowMessage('des error');
}

end;

end.


参考 http://www.unpack.cn/thread-35739-1-1.html
http://www.cnblogs.com/enli/archive/2008/07/10/1240144.html
PB Lock Box下载:http://sourceforge.net/projects/tplockbox
安装:D7 source, lib路径加入控件source, 安装package vc70.dpk

你可能感兴趣的:(Delphi)