Javaでの3 DES暗号化とC#の互換性

4872 ワード

附:近日のプロジェクトは他社と提携して開発したもので、パスワードを送信する際に3 DES暗号化方式で暗号化することを提案されました.相手はBASE 64符号化のkeyとベクトルIVを提供しており、C#言語を使用し、3 DES暗号化を行う際にCBCモード、Zeros充填方式を使用している.こちらはjava言語を使っています.Googleでは、2つの言語の間に2つの互換性があることがわかりました.1.C#はCBC Mode、PKCS 7 Padding、JavaはCBC Mode、PKCS 5 Padding Padding 2.C#はECB Mode、PKCS 7 Padding、JavaはECB Mode、PKCS 5 Padding Paddingが採用されていますが、今回の提携では、C#の充填方式がZeros、CBCモードであることに悩んでいます.大量のGoogleの後、解決策が見つかったので、記録します.JavaではCBCモード、NoPaddingで塗りつぶします.暗号化時に自分でパスワードの埋め込み(バイトゼロで埋め)を完了することで、C#のCBCモードZeros埋め込み方式の暗号化結果と同じことが保証されます.
 
 
コード:
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

import org.apache.commons.codec.binary.Base64;

/**
 *     DESede   3des    <p>
 *     CBC,ECB。 CBC     key,  iv; ECB      key。<p>
 *     NoPadding、PKCS5Padding、SSL3Padding。<p>
 *        :<br>
 *    C#  CBC Mode,PKCS7 Padding,Java  CBC Mode,PKCS5Padding Padding,<br>
 *     C#  ECB Mode,PKCS7 Padding,Java  ECB Mode,PKCS5Padding Padding,
 * <p>
 *        CBC  NoPadding    、      ,     C#   CBC  ,zeros    。
 */
public class ThreeDES {

	/**
	 *   BASE64   KEY
	 */
	private static final String BASE64_key = "12345678901234567890123456789012";
	/**
	 *   IV
	 */
	private static final String _IV = "12345678";
	private final static String Algorithm = "DESede/CBC/NoPadding";//    /    /    
	/*     DESede   3des    
	 *     CBC,ECB。 CBC     key,  iv; ECB      key。
	 *     NoPadding、PKCS5Padding、SSL3Padding。
	 *        :
	 *    C#  CBC Mode,PKCS7 Padding,Java  CBC Mode,PKCS5Padding Padding,
	 *     C#  ECB Mode,PKCS7 Padding,Java  ECB Mode,PKCS5Padding Padding,
	 */
	private static SecureRandom sr = new SecureRandom();
	private static SecretKeyFactory keyFactory;
	private static DESedeKeySpec dks;
	private static SecretKey securekey;
	private static IvParameterSpec ips;

	static {
		
		//  jce  (sun      )
		Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		try {
			dks = new DESedeKeySpec(Base64.decodeBase64(BASE64_key.getBytes("UTF-8")));
			keyFactory = SecretKeyFactory.getInstance("DESede");
			securekey = keyFactory.generateSecret(dks);
			ips = new IvParameterSpec(_IV.getBytes("UTF-8"));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 3des  
	 * @param password   
	 * @return      
	 */
	public static String encrypt(String password){
		
		Cipher cipher;
		String result = null;
		try {
			cipher = Cipher.getInstance(Algorithm);
			cipher.init(Cipher.ENCRYPT_MODE, securekey, ips, sr);
			byte [] arry = cipher.doFinal(FormateData(password));
			result = new String(Base64.encodeBase64(arry),"UTF-8");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return result;
	}
	
	/**
	 * 3des  
	 *  @param password   
	 *  @return      
	 */
	public static String decrypt(String password){
		
		Cipher cipher;
		String result = null;
		try {

			cipher = Cipher.getInstance(Algorithm);
			cipher.init(Cipher.DECRYPT_MODE, securekey, ips, sr);
			byte [] arry = cipher.doFinal(Base64.decodeBase64(password.getBytes("UTF-8")));
			result = new String(FormateByte(arry));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return result;
	}
	
	/**
	 *      ,      8   。<p>
	 * (       CBC  ,     NoPadding      ,      .)
	 *	
	 * @param str
	 * 			  
	 * @return       
	 */
	public static byte [] FormateData(String str) throws UnsupportedEncodingException{
		
		int yu = str.length() % 8;
		if(yu != 0){
			int size = 8 - yu;
			byte [] arr = new byte [str.length() + size];
			byte [] data = str.getBytes("UTF-8");
			int i = 0;
			for (; i < data.length; i++) {
				arr[i] = data[i];
			}
			for (int j = 0; j < size; j++,i++) {
				arr[i] = new byte [] {0}[0];
			}
			return arr;
		}
		return str.getBytes("UTF-8");
	}
	
	/**
	 *      ,         !<p>
	 * (        CBC  ,     NoPadding  ,             。)
	 * @param arr
	 * 			     
	 * 
	 * @return      
	 */
	public static byte [] FormateByte(byte [] arr){
		
		int i = 0;
		for (; i < arr.length; i++) {
			if(arr[i] == new Byte("0")){
				break;
			}
		}
		byte [] result = new byte [i];
		for (int j = 0; j < i; j++) {
			result[j] = arr[j];
		}
		return result;
	}
	
	public static void main(String[] args) {
		String a = encrypt("12345612345612345");
		System.out.println(a);
		System.out.println(decrypt(a));
	}
}
  • 3DES.rar (1.6 MB)

  • 原文:http://zhcheng.iteye.com/blog/1052309