最近 一个项目.net 要调用JAVA的WEB
SERVICE,数据采用3DES加密,涉及到两种语言3DES一致性的问题,
下面分享一下,
这里的KEY采用Base64编码,便用分发,因为Java的Byte范围为-128至127,c#的Byte范围是0-255
核心是确定Mode和Padding,关于这两个的意思可以搜索3DES算法相关文章
一个是C#采用CBC
Mode,PKCS7 Padding,Java采用CBC Mode,PKCS5Padding Padding,
另一个是C#采用ECB
Mode,PKCS7 Padding,Java采用ECB Mode,PKCS5Padding
Padding,
Java的ECB模式不需要IV
对字符加密时,双方采用的都是UTF-8编码
下面是C#代码
///
<summary>
///
DES3加密解密
///
</summary>
public
class
Des3
{
#region
CBC模式**
///
<summary>
///
DES3 CBC模式加密
///
</summary>
///
<param name="key">
密钥
</param>
///
<param name="iv">
IV
</param>
///
<param name="data">
明文的byte数组
</param>
///
<returns>
密文的byte数组
</returns>
public
static
byte
[] Des3EncodeCBC(
byte
[] key,
byte
[] iv,
byte
[] data )
{
//
复制于MSDN
try
{
//
Create a MemoryStream.
MemoryStream mStream
=
new
MemoryStream();
TripleDESCryptoServiceProvider tdsp
=
new
TripleDESCryptoServiceProvider();
tdsp.Mode
=
CipherMode.CBC;
//
默认值
tdsp.Padding
=
PaddingMode.PKCS7;
//
默认值
//
Create a CryptoStream using the MemoryStream
//
and the passed key and initialization vector (IV).
CryptoStream cStream
=
new
CryptoStream( mStream,
tdsp.CreateEncryptor( key, iv ),
CryptoStreamMode.Write );
//
Write the byte array to the crypto stream and flush it.
cStream.Write( data,
0
, data.Length );
cStream.FlushFinalBlock();
//
Get an array of bytes from the
//
MemoryStream that holds the
//
encrypted data.
byte
[] ret
=
mStream.ToArray();
//
Close the streams.
cStream.Close();
mStream.Close();
//
Return the encrypted buffer.
return
ret;
}
catch
( CryptographicException e )
{
Console.WriteLine(
"
A Cryptographic error occurred: {0}
"
, e.Message );
return
null
;
}
}
///
<summary>
///
DES3 CBC模式解密
///
</summary>
///
<param name="key">
密钥
</param>
///
<param name="iv">
IV
</param>
///
<param name="data">
密文的byte数组
</param>
///
<returns>
明文的byte数组
</returns>
public
static
byte
[] Des3DecodeCBC(
byte
[] key,
byte
[] iv,
byte
[] data )
{
try
{
//
Create a new MemoryStream using the passed
//
array of encrypted data.
MemoryStream msDecrypt
=
new
MemoryStream( data );
TripleDESCryptoServiceProvider tdsp
=
new
TripleDESCryptoServiceProvider();
tdsp.Mode
=
CipherMode.CBC;
tdsp.Padding
=
PaddingMode.PKCS7;
//
Create a CryptoStream using the MemoryStream
//
and the passed key and initialization vector (IV).
CryptoStream csDecrypt
=
new
CryptoStream( msDecrypt,
tdsp.CreateDecryptor( key, iv ),
CryptoStreamMode.Read );
//
Create buffer to hold the decrypted data.
byte
[] fromEncrypt
=
new
byte
[data.Length];
//
Read the decrypted data out of the crypto stream
//
and place it into the temporary buffer.
csDecrypt.Read( fromEncrypt,
0
, fromEncrypt.Length );
//
Convert the buffer into a string and return it.
return
fromEncrypt;
}
catch
( CryptographicException e )
{
Console.WriteLine(
"
A Cryptographic error occurred: {0}
"
, e.Message );
return
null
;
}
}
#endregion
#region
ECB模式
///
<summary>
///
DES3 ECB模式加密
///
</summary>
///
<param name="key">
密钥
</param>
///
<param name="iv">
IV(当模式为ECB时,IV无用)
</param>
///
<param name="str">
明文的byte数组
</param>
///
<returns>
密文的byte数组
</returns>
public
static
byte
[] Des3EncodeECB(
byte
[] key,
byte
[] iv,
byte
[] data )
{
try
{
//
Create a MemoryStream.
MemoryStream mStream
=
new
MemoryStream();
TripleDESCryptoServiceProvider tdsp
=
new
TripleDESCryptoServiceProvider();
tdsp.Mode
=
CipherMode.ECB;
tdsp.Padding
=
PaddingMode.PKCS7;
//
Create a CryptoStream using the MemoryStream
//
and the passed key and initialization vector (IV).
CryptoStream cStream
=
new
CryptoStream( mStream,
tdsp.CreateEncryptor( key, iv ),
CryptoStreamMode.Write );
//
Write the byte array to the crypto stream and flush it.
cStream.Write( data,
0
, data.Length );
cStream.FlushFinalBlock();
//
Get an array of bytes from the
//
MemoryStream that holds the
//
encrypted data.
byte
[] ret
=
mStream.ToArray();
//
Close the streams.
cStream.Close();
mStream.Close();
//
Return the encrypted buffer.
return
ret;
}
catch
( CryptographicException e )
{
Console.WriteLine(
"
A Cryptographic error occurred: {0}
"
, e.Message );
return
null
;
}
}
///
<summary>
///
DES3 ECB模式解密
///
</summary>
///
<param name="key">
密钥
</param>
///
<param name="iv">
IV(当模式为ECB时,IV无用)
</param>
///
<param name="str">
密文的byte数组
</param>
///
<returns>
明文的byte数组
</returns>
public
static
byte
[] Des3DecodeECB(
byte
[] key,
byte
[] iv,
byte
[] data )
{
try
{
//
Create a new MemoryStream using the passed
//
array of encrypted data.
MemoryStream msDecrypt
=
new
MemoryStream( data );
TripleDESCryptoServiceProvider tdsp
=
new
TripleDESCryptoServiceProvider();
tdsp.Mode
=
CipherMode.ECB;
tdsp.Padding
=
PaddingMode.PKCS7;
//
Create a CryptoStream using the MemoryStream
//
and the passed key and initialization vector (IV).
CryptoStream csDecrypt
=
new
CryptoStream( msDecrypt,
tdsp.CreateDecryptor( key, iv ),
CryptoStreamMode.Read );
//
Create buffer to hold the decrypted data.
byte
[] fromEncrypt
=
new
byte
[data.Length];
//
Read the decrypted data out of the crypto stream
//
and place it into the temporary buffer.
csDecrypt.Read( fromEncrypt,
0
, fromEncrypt.Length );
//
Convert the buffer into a string and return it.
return
fromEncrypt;
}
catch
( CryptographicException e )
{
Console.WriteLine(
"
A Cryptographic error occurred: {0}
"
, e.Message );
return
null
;
}
}
#endregion
///
<summary>
///
类测试
///
</summary>
public
static
void
Test()
{
System.Text.Encoding utf8
=
System.Text.Encoding.UTF8;
//
key为abcdefghijklmnopqrstuvwx的Base64编码
byte
[] key
=
Convert.FromBase64String(
"
YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4
"
);
byte
[] iv
=
new
byte
[] {
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
//
当模式为ECB时,IV无用
byte
[] data
=
utf8.GetBytes(
"
中国ABCabc123
"
);
System.Console.WriteLine(
"
ECB模式:
"
);
byte
[] str1
=
Des3.Des3EncodeECB( key, iv, data );
byte
[] str2
=
Des3.Des3DecodeECB( key, iv, str1 );
System.Console.WriteLine( Convert.ToBase64String( str1 ) );
System.Console.WriteLine( System.Text.Encoding.UTF8.GetString( str2 ) );
System.Console.WriteLine();
System.Console.WriteLine(
"
CBC模式:
"
);
byte
[] str3
=
Des3.Des3EncodeCBC( key, iv, data );
byte
[] str4
=
Des3.Des3DecodeCBC( key, iv, str3 );
System.Console.WriteLine( Convert.ToBase64String( str3 ) );
System.Console.WriteLine( utf8.GetString( str4 ) );
System.Console.WriteLine();
}
}
接着是Java代码
import
java.security.Key;
import
javax.crypto.Cipher;
import
javax.crypto.SecretKeyFactory;
import
javax.crypto.spec.DESedeKeySpec;
import
javax.crypto.spec.IvParameterSpec;
import
sun.misc.BASE64Decoder;
import
sun.misc.BASE64Encoder;
public
class
Des3 {
public
static
void
main(String[] args)
throws
Exception {
byte
[] key
=
new
BASE64Decoder().decodeBuffer(
"
YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4
"
);
byte
[] keyiv
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
byte
[] data
=
"
中国ABCabc123
"
.getBytes(
"
UTF-8
"
);
System.out.println(
"
ECB加密解密
"
);
byte
[] str3
=
des3EncodeECB(key,data );
byte
[] str4
=
ees3DecodeECB(key, str3);
System.out.println(
new
BASE64Encoder().encode(str3));
System.out.println(
new
String(str4,
"
UTF-8
"
));
System.out.println();
System.out.println(
"
CBC加密解密
"
);
byte
[] str5
=
des3EncodeCBC(key, keyiv, data);
byte
[] str6
=
des3DecodeCBC(key, keyiv, str5);
System.out.println(
new
BASE64Encoder().encode(str5));
System.out.println(
new
String(str6,
"
UTF-8
"
));
}
/**
* ECB加密,不要IV
*
@param
key 密钥
*
@param
data 明文
*
@return
Base64编码的密文
*
@throws
Exception
*/
public
static
byte
[] des3EncodeECB(
byte
[] key,
byte
[] data)
throws
Exception {
Key deskey
=
null
;
DESedeKeySpec spec
=
new
DESedeKeySpec(key);
SecretKeyFactory keyfactory
=
SecretKeyFactory.getInstance(
"
desede
"
);
deskey
=
keyfactory.generateSecret(spec);
Cipher cipher
=
Cipher.getInstance(
"
desede
"
+
"
/ECB/PKCS5Padding
"
);
cipher.init(Cipher.ENCRYPT_MODE, deskey);
byte
[] bOut
=
cipher.doFinal(data);
return
bOut;
}
/**
* ECB解密,不要IV
*
@param
key 密钥
*
@param
data Base64编码的密文
*
@return
明文
*
@throws
Exception
*/
public
static
byte
[] ees3DecodeECB(
byte
[] key,
byte
[] data)
throws
Exception {
Key deskey
=
null
;
DESedeKeySpec spec
=
new
DESedeKeySpec(key);
SecretKeyFactory keyfactory
=
SecretKeyFactory.getInstance(
"
desede
"
);
deskey
=
keyfactory.generateSecret(spec);
Cipher cipher
=
Cipher.getInstance(
"
desede
"
+
"
/ECB/PKCS5Padding
"
);
cipher.init(Cipher.DECRYPT_MODE, deskey);
byte
[] bOut
=
cipher.doFinal(data);
return
bOut;
}
/**
* CBC加密
*
@param
key 密钥
*
@param
keyiv IV
*
@param
data 明文
*
@return
Base64编码的密文
*
@throws
Exception
*/
public
static
byte
[] des3EncodeCBC(
byte
[] key,
byte
[] keyiv,
byte
[] data)
throws
Exception {
Key deskey
=
null
;
DESedeKeySpec spec
=
new
DESedeKeySpec(key);
SecretKeyFactory keyfactory
=
SecretKeyFactory.getInstance(
"
desede
"
);
deskey
=
keyfactory.generateSecret(spec);
Cipher cipher
=
Cipher.getInstance(
"
desede
"
+
"
/CBC/PKCS5Padding
"
);
IvParameterSpec ips
=
new
IvParameterSpec(keyiv);
cipher.init(Cipher.ENCRYPT_MODE, deskey, ips);
byte
[] bOut
=
cipher.doFinal(data);
return
bOut;
}
/**
* CBC解密
*
@param
key 密钥
*
@param
keyiv IV
*
@param
data Base64编码的密文
*
@return
明文
*
@throws
Exception
*/
public
static
byte
[] des3DecodeCBC(
byte
[] key,
byte
[] keyiv,
byte
[] data)
throws
Exception {
Key deskey
=
null
;
DESedeKeySpec spec
=
new
DESedeKeySpec(key);
SecretKeyFactory keyfactory
=
SecretKeyFactory.getInstance(
"
desede
"
);
deskey
=
keyfactory.generateSecret(spec);
Cipher cipher
=
Cipher.getInstance(
"
desede
"
+
"
/CBC/PKCS5Padding
"
);
IvParameterSpec ips
=
new
IvParameterSpec(keyiv);
cipher.init(Cipher.DECRYPT_MODE, deskey, ips);
byte
[] bOut
=
cipher.doFinal(data);
return
bOut;
}
}
下面是运行结果
ECB模式:
rmWB4+r9Ug93WI0KAEuMig==
中国ABCabc123
CBC模式:
4aabWF8UFour/vNfnzJrjw==
中国ABCabc123
另外,android下要使用3DES可考虑将BASE64Encoder替换成Base64
代码如下:
public
static
void
main(String[] args)
throws
Exception {
byte
[] key
=
Base64.decode(
"
YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4
"
.getBytes(),Base64.DEFAULT);
byte
[] keyiv
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
byte
[] data
=
"
中国ABCabc123
"
.getBytes(
"
UTF-8
"
);
System.out.println(
"
ECB加密解密
"
);
byte
[] str3
=
des3EncodeECB(key,data );
byte
[] str4
=
ees3DecodeECB(key, str3);
System.out.println(
new
String(Base64.encode(str3, Base64.DEFAULT),
"
UTF-8
"
));
System.out.println(
new
String(str4,
"
UTF-8
"
));
System.out.println();
System.out.println(
"
CBC加密解密
"
);
byte
[] str5
=
des3EncodeCBC(key, keyiv, data);
byte
[] str6
=
des3DecodeCBC(key, keyiv, str5);
System.out.println(
new
String(Base64.encode(str5, Base64.DEFAULT),
"
UTF-8
"
));
System.out.println(
new
String(str6,
"
UTF-8
"
));
}