개발자인생YO
731
2019-05-07 15:09:23 작성 2019-05-07 16:11:35 수정됨
2
3050

자바 aes256 cbc모드 iv값 질문드립니다~


암호화같은경우는 아래와 같이 iv 값이 없어도 되는거같은데

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");

c.init(Cipher.ENCRYPT_MODE, keySpec);


복호화는 아래와 같이 하면 " Parameters missing " 오류가 생깁니다

Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");

c.init(Cipher.DECRYPT_MODE, keySpec);



복호화는 iv값이 필수인건가요?


아래는 전체 코드입니다.


package test;

import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;

public class AES256Util {

	private String iv;
	private Key keySpec;

	/**
	 * 16자리의 키값을 입력하여 객체를 생성한다.
	 * 
	 * @param key 암/복호화를 위한 키값
	 * @throws UnsupportedEncodingException 키값의 길이가 16이하일 경우 발생
	 */
	
	String key = "키값"; // key는 16자 이상

	public AES256Util() throws UnsupportedEncodingException {
		this.iv = null;
		byte[] keyBytes = new byte[32];
		byte[] b = key.getBytes("UTF-8");
		int len = b.length;
		if (len > keyBytes.length) {
			len = keyBytes.length;
		}
		System.arraycopy(b, 0, keyBytes, 0, len);
		SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");

		this.keySpec = keySpec;
	}

	/**
	 * AES256 으로 암호화 한다.
	 * 
	 * @param str 암호화할 문자열
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws GeneralSecurityException
	 * @throws UnsupportedEncodingException
	 */
	public String encrypt(String str)
			throws NoSuchAlgorithmException, GeneralSecurityException, UnsupportedEncodingException {
		Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
		c.init(Cipher.ENCRYPT_MODE, keySpec);
		byte[] encrypted = c.doFinal(str.getBytes("UTF-8"));
		String enStr = new String(Base64.encodeBase64(encrypted));
		return enStr;
	}

	/**
	 * AES256으로 암호화된 txt 를 복호화한다.
	 * 
	 * @param str 복호화할 문자열
	 * @return
	 * @throws NoSuchAlgorithmException
	 * @throws GeneralSecurityException
	 * @throws UnsupportedEncodingException
	 */
	public String decrypt(String str)
			throws NoSuchAlgorithmException, GeneralSecurityException, UnsupportedEncodingException {
		Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
		c.init(Cipher.DECRYPT_MODE, keySpec);
		byte[] byteStr = Base64.decodeBase64(str.getBytes());
		return new String(c.doFinal(byteStr), "UTF-8");
	}
}



===============================================================================

추가


아래 처럼 해보면 

this.iv = null;


c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes()));

c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv.getBytes()));



java.lang.NullPointerException

at test.AES256Util.encrypt(AES256Util.java:52)

at test.Go.test(Go.java:22)

at test.Go.main(Go.java:8)

같은 오류가 생깁니다



간단히 말씀드리자면 iv를 null 값으로 쓰든 아예 사용하지않든 cbc모드에서 암호화,복호화가 가능한가요?

0
  • 답변 2

  • Deer Hunter
    328
    2019-05-08 03:25:44

    CBC mode를 간단하게 말하자면, 이전 block의 암호화된 결과물을, 다음의 평문 block 과 XOR 연산 후 암호화 하는 것입니다.

    이때 최초 block의 경우 XOR 연산을 수행할 대상인 이전 block이 없으므로, IV(Initial Vector)를 이용하여 연산을 합니다.

    그러므로 CBC mode에서는 IV가 필요합니다.

  • 개발자인생YO
    731
    2019-05-08 15:54:39

    Deer Hunter



    package test;
    
    import java.io.UnsupportedEncodingException;
    import java.security.GeneralSecurityException;
    import java.security.Key;
    import java.security.NoSuchAlgorithmException;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import org.apache.commons.codec.binary.Base64;
    
    public class AES256Util {
    
    	private byte[] iv;
    	private Key keySpec;
    
    	/**
    	 * 16자리의 키값을 입력하여 객체를 생성한다.
    	 * 
    	 * @param key 암/복호화를 위한 키값
    	 * @throws UnsupportedEncodingException 키값의 길이가 16이하일 경우 발생
    	 */
    	
    	String key = "키값"; // key는 16자 이상
    
    	public AES256Util() throws UnsupportedEncodingException {
    		this.iv = new byte[16];
    		byte[] keyBytes = new byte[32];
    		
    		byte[] b = key.getBytes("UTF-8");
    		int len = b.length;
    		if (len > keyBytes.length) {
    			len = keyBytes.length;
    		}
    		System.arraycopy(b, 0, keyBytes, 0, len);
    		SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
    
    		this.keySpec = keySpec;
    	}
    
    	/**
    	 * AES256 으로 암호화 한다.
    	 * 
    	 * @param str 암호화할 문자열
    	 * @return
    	 * @throws NoSuchAlgorithmException
    	 * @throws GeneralSecurityException
    	 * @throws UnsupportedEncodingException
    	 */
    	public String encrypt(String str)
    			throws NoSuchAlgorithmException, GeneralSecurityException, UnsupportedEncodingException {
    		Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
    		c.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));
    		byte[] encrypted = c.doFinal(str.getBytes("UTF-8"));
    		String enStr = new String(Base64.encodeBase64(encrypted));
    		return enStr;
    	}
    
    	/**
    	 * AES256으로 암호화된 text 를 복호화한다.
    	 * 
    	 * @param str 복호화할 문자열
    	 * @return
    	 * @throws NoSuchAlgorithmException
    	 * @throws GeneralSecurityException
    	 * @throws UnsupportedEncodingException
    	 */
    	public String decrypt(String str)
    			throws NoSuchAlgorithmException, GeneralSecurityException, UnsupportedEncodingException {
    		Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
    		c.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
    		byte[] byteStr = Base64.decodeBase64(str.getBytes());
    		return new String(c.doFinal(byteStr), "UTF-8");
    	}
    }
    


    위 코드와 같이 this.iv = new byte[16]; 이렇게 해봤는데

    iv에 값을 이렇게 줘도 될까요?



  • 로그인을 하시면 답변 을 등록할 수 있습니다.