반응형
package ase; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.AlgorithmParameters; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.KeySpec; import java.util.logging.Level; import java.util.logging.Logger; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; public class AES128_File { public static String byteToHex(byte[] raw) { String HEXES = "0123456789ABCDEF"; if (raw == null) { return null; } final StringBuilder hex = new StringBuilder(2 * raw.length); for (final byte b : raw) { hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F))); } return hex.toString(); } public static byte[] hexToByte(String hexString) { int len = hexString.length(); byte[] ba = new byte[len / 2]; for (int i = 0; i < len; i += 2) { ba[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16)); } return ba; } /** * @param msg */ private void cryptMessage(String msg) { System.out.println("** Crypt ** " + msg); } /** * @param input * - the cleartext file to be encrypted * @param output * - the encrypted data file * @throws IOException * @throws IllegalBlockSizeException * @throws BadPaddingException */ public void WriteEncryptedFile(String cryptKey,InputStream inputStream, OutputStream outputStream) throws IOException, IllegalBlockSizeException, BadPaddingException { try { int SALT_LEN = 8; byte[] mInitVec = null; byte[] mSalt = new byte[SALT_LEN]; Cipher mEcipher = null; int KEYLEN_BITS = 128; // see notes below where this is used. int ITERATIONS = 65536; int MAX_FILE_BUF = 2048; long totalread = 0; int nread = 0; byte[] inbuf = new byte[MAX_FILE_BUF]; SecretKeyFactory factory = null; SecretKey tmp = null; mSalt = new byte[SALT_LEN]; SecureRandom rnd = new SecureRandom(); rnd.nextBytes(mSalt); cryptMessage("generated salt :" + byteToHex(mSalt)); factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(cryptKey.toCharArray(), mSalt, ITERATIONS, KEYLEN_BITS); tmp = factory.generateSecret(spec); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); mEcipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); mEcipher.init(Cipher.ENCRYPT_MODE, secret); AlgorithmParameters params = mEcipher.getParameters(); mInitVec = params.getParameterSpec(IvParameterSpec.class).getIV(); System.out.println("mInitVec : " + mInitVec); cryptMessage("mInitVec is :" + byteToHex(mInitVec)); outputStream.write(mSalt); outputStream.write(mInitVec); while ((nread = inputStream.read(inbuf)) > 0) { cryptMessage("read " + nread + " bytes"); totalread += nread; byte[] trimbuf = new byte[nread]; for (int i = 0; i < nread; i++) { trimbuf[i] = inbuf[i]; } byte[] tmpBuf = mEcipher.update(trimbuf); if (tmpBuf != null) { outputStream.write(tmpBuf); } } byte[] finalbuf = mEcipher.doFinal(); if (finalbuf != null) { outputStream.write(finalbuf); } outputStream.flush(); inputStream.close(); outputStream.close(); outputStream.close(); cryptMessage("wrote " + totalread + " encrypted bytes"); System.out.println("파일 암호화 성공"); } catch (InvalidKeyException ex) { Logger.getLogger(AES128_File.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidParameterSpecException ex) { Logger.getLogger(AES128_File.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchAlgorithmException ex) { Logger.getLogger(AES128_File.class.getName()).log(Level.SEVERE, null, ex); } catch (NoSuchPaddingException ex) { Logger.getLogger(AES128_File.class.getName()).log(Level.SEVERE, null, ex); } catch (InvalidKeySpecException ex) { Logger.getLogger(AES128_File.class.getName()).log(Level.SEVERE, null, ex); } } /** * Read from the encrypted file (input) and turn the cipher back into * cleartext. Write the cleartext buffer back out to disk as (output) File. * * I left CipherInputStream in here as a test to see if I could mix it with * the update() and final() methods of encrypting and still have a correctly * decrypted file in the end. Seems to work so left it in. * * @param input * - File object representing encrypted data on disk * @param output * - File object of cleartext data to write out after decrypting * @throws IllegalBlockSizeException * @throws BadPaddingException * @throws IOException */ public void ReadEncryptedFile(String cryptKey,InputStream inputStream, OutputStream outputStream) throws IllegalBlockSizeException, BadPaddingException, IOException { try { int SALT_LEN = 8; byte[] mInitVec = null; byte[] mSalt = new byte[SALT_LEN]; Cipher mDecipher = null; int KEYLEN_BITS = 128; // see notes below where this is used. int ITERATIONS = 65536; int MAX_FILE_BUF = 2048; CipherInputStream cin; long totalread = 0; int nread = 0; byte[] inbuf = new byte[MAX_FILE_BUF]; SecretKeyFactory factory = null; SecretKey tmp = null; // SecretKey secret = null; // Read the Salt inputStream.read(mSalt); cryptMessage("generated salt :" + byteToHex(mSalt)); factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1"); KeySpec spec = new PBEKeySpec(cryptKey.toCharArray(), mSalt, ITERATIONS, KEYLEN_BITS); tmp = factory.generateSecret(spec); SecretKey secret = new SecretKeySpec(tmp.getEncoded(), "AES"); mDecipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); mDecipher.init(Cipher.ENCRYPT_MODE, secret); AlgorithmParameters params = mDecipher.getParameters(); mInitVec = params.getParameterSpec(IvParameterSpec.class).getIV(); inputStream.read(mInitVec); cryptMessage("mInitVec is :" + byteToHex(mInitVec)); mDecipher.init(Cipher.DECRYPT_MODE, secret, new IvParameterSpec(mInitVec)); cin = new CipherInputStream(inputStream, mDecipher); System.out.println("inbuf.length : " + inbuf.length); while ((nread = cin.read(inbuf)) > 0) { // Db("read " + nread + " bytes"); totalread += nread; byte[] trimbuf = new byte[nread]; for (int i = 0; i < nread; i++) { trimbuf[i] = inbuf[i]; } // write out the size-adjusted buffer outputStream.write(trimbuf); } outputStream.flush(); cin.close(); inputStream.close(); outputStream.close(); cryptMessage("wrote " + totalread + " encrypted bytes"); } catch (Exception ex) { ex.getStackTrace(); Logger.getLogger(AES128_File.class.getName()).log(Level.SEVERE, null, ex); } } /** * adding main() for usage demonstration. With member vars, some of the * locals would not be needed */ public static void main(String[] args) { // create the input.txt file in the current directory before continuing File input = new File("C:\\Test\\test.txt"); File eoutput = new File("C:\\Test\\test.aes"); File doutput = new File("C:\\Test\\decrypted1.txt"); String iv = null; String salt = null; AES128_File aesFile = new AES128_File(); String cryptKey = "1q2w3e"; /* * write out encrypted file */ try { aesFile.WriteEncryptedFile(cryptKey,new FileInputStream(input), new FileOutputStream(eoutput)); System.out.printf("File encrypted to " + eoutput.getName() + "\niv:" + iv + "\nsalt:" + salt + "\n\n"); } catch (IllegalBlockSizeException | BadPaddingException | IOException e) { e.printStackTrace(); } /* * decrypt file */ /* * write out decrypted file */ try { aesFile.ReadEncryptedFile(cryptKey,new FileInputStream(eoutput), new FileOutputStream(doutput)); System.out.println("decryption finished to " + doutput.getName()); } catch (IllegalBlockSizeException | BadPaddingException | IOException e) { e.printStackTrace(); } } }
'JAVA > Java' 카테고리의 다른 글
이클립스에 EGit 플러그인 설치 후 Github 연동 (0) | 2016.05.20 |
---|---|
eclipse에 github 연결해서 웹저장소에서 버전관리(repository)하기 (0) | 2016.05.20 |
JAVA swing custum Dialog 만들기 (0) | 2016.05.20 |
AES, SHA256 암 복호화 (0) | 2016.03.02 |
java String Calss (0) | 2015.03.18 |