JAva-信頼性の高い安全なチャネルを非安全なネットワーク上に確立(3/3)

5585 ワード

このブログの最初の2つのセクション(1/3,2/3)では、安全でないネットワーク環境の下で双方のアイデンティティを相互に認証する方法(信頼できる接続を確立する方法)と、それに基づいて信頼できる鍵交渉(DHアルゴリズム)を紹介しています.
このセクションでは、チャネル上に流れるデータを、協議された鍵を使用して暗号化する方法について説明します.対称鍵のアルゴリズムとしてAESを使用します.鍵強度:128ビットです.このプロセスは、次の2つのステップに簡単にまとめることができます.
 
  • は、ネゴシエートされたkeyを使用して、暗号化および復号化に使用できるAes Cipherを作成する.
  • このcipherを使用してbyte配列を暗号化および復号化する.

  • コードを直接付けましょう.
    /**
     *   AES 128bit              
     * 
     * @author atlas
     * @date 2012-9-18
     */
    public class AESCipher {
    	private static final int bsize = 16;
    	private static final int ivsize = 16;
    	private Cipher dCipher;
    	private Cipher eCipher;
    
    	private AESCipher(Cipher dCipher, Cipher eCipher) {
    		this.eCipher = eCipher;
    		this.dCipher = dCipher;
    	}
    
    	public static AESCipher getInstance(byte[] key) throws CryptoException {
    		String pad = "PKCS5Padding";
    		try {
    			byte[] tmpKey = ChecksumUtil.getChecksumAsBytes("md5", key);
    			byte[] tmpIV = new byte[ivsize];
    			if (key.length <= ivsize) {
    				System.arraycopy(key, 0, tmpKey, 0, key.length);
    			} else if (key.length > ivsize) {
    				System.arraycopy(key, 0, tmpIV, 0, tmpIV.length);
    			}
    			SecretKeySpec keyspec = new SecretKeySpec(tmpKey, "AES");
    			IvParameterSpec ivSpec = new IvParameterSpec(tmpIV);
    			Cipher dcipher = Cipher.getInstance("AES/CBC/" + pad);
    			Cipher ecipher = Cipher.getInstance("AES/CBC/" + pad);
    			ecipher.init(Cipher.ENCRYPT_MODE, keyspec, ivSpec);
    			dcipher.init(Cipher.DECRYPT_MODE, keyspec, ivSpec);
    			return new AESCipher(dcipher, ecipher);
    		} catch (Exception e) {
    			throw new CryptoException("initializing AESCipher fail.", e);
    		}
    	}
    
    	/**
    	 * 
    	 * @param str
    	 * @return
    	 * @throws CryptoException
    	 */
    	public String encrypt(String str) throws CryptoException {
    		try {
    			// Encode the string into bytes using utf-8
    			byte[] utf8 = str.getBytes("UTF8");
    			// Encrypt
    			byte[] enc = this.eCipher.doFinal(utf8);
    			// Encode bytes to hex string
    			return StringUtils.bytesToHex(enc);
    		} catch (Exception e) {
    			throw new CryptoException("encrypt failed.", e);
    		}
    	}
    
    	public String decrypt(String str) throws CryptoException {
    		try {
    			byte[] dec = StringUtils.hexToBytes(str);
    			// Decrypt
    			byte[] utf8 = this.dCipher.doFinal(dec);
    			// Decode using utf-8
    			return new String(utf8, "UTF8");
    		} catch (Exception e) {
    			throw new CryptoException("decrypt failed.", e);
    		}
    	}
    
    	public byte[] encrypt(byte[] message) throws CryptoException {
    		try {
    			// Encrypt
    			return this.eCipher.doFinal(message);
    		} catch (Exception e) {
    			throw new CryptoException("encrypt failed.", e);
    		}
    	}
    
    	/**
    	 *                   ,input buffer output
    	 * buffer     byte  ,         output             ,         padding。
    	 *   padding     {@link #getBsize() }-1
    	 * 
    	 * @param input
    	 *                buffer
    	 * @param inputOffset
    	 *                   input buffer      ( 0  )
    	 * @param inputLen
    	 *                     ,   (input.length-inputOffset).
    	 * @param output
    	 *                     buffer。
    	 * @param outputOffset
    	 *              buffer     。
    	 * @return  output           
    	 * 
    	 * @throws ShortBufferException
    	 *               output buffer  ,        
    	 */
    	public int encrypt(byte[] input, int inputOffset, int inputLen,
    			byte[] output, int outputOffset) throws CryptoException {
    		try {
    			return eCipher.doFinal(input, inputOffset, inputLen, output,
    					outputOffset);
    		} catch (Exception e) {
    			throw new CryptoException("encryption failed", e);
    		}
    	}
    
    	/**
    	 *                   ,input buffer output buffer      byte  。
    	 * 
    	 * @param input
    	 *                buffer
    	 * @param inputOffset
    	 *                   input buffer      ( 0  )
    	 * @param inputLen
    	 *                     ,   (input.length-inputOffset).
    	 * @param output
    	 *                     buffer。
    	 * @param outputOffset
    	 *              buffer     。
    	 * @return  output           
    	 * @throws ShortBufferException
    	 *               output buffer  ,        
    	 */
    	public int decrypt(byte[] input, int inputOffset, int inputLen,
    			byte[] output, int outputOffset) throws CryptoException {
    		try {
    			return dCipher.doFinal(input, inputOffset, inputLen, output,
    					outputOffset);
    		} catch (Exception e) {
    			throw new CryptoException("decryption failed", e);
    		}
    	}
    
    	/**
    	 *      padding   
    	 * 
    	 * @param len
    	 * @return
    	 */
    	public int pad(int len) {
    		return eCipher.getOutputSize(len) - len;
    	}
    
    	public byte[] decrypt(byte[] message) throws CryptoException {
    		try {
    			// Decrypted
    			byte[] decrypted = this.dCipher.doFinal(message);
    			return decrypted;
    		} catch (Exception e) {
    			throw new CryptoException("decrypt failed.", e);
    		}
    	}
    }

     
    いくつかのツールクラスのコードは貼らない.