2014-01-15 7 views
0

AES를 사용하여 텍스트를 암호화/해독하는 클래스를 작성하려고합니다.AES 키 문자열이 예외를 throw합니다.

키를 생성하고 키를 데이터베이스 열에 저장하고 해당 키를 사용하여 키가 들어있는 데이터베이스 행의 해당 텍스트를 암호화/해독합니다.

다음은 키를 생성하고 암호화 및 암호 해독 작업을 수행하기 위해 작성한 클래스입니다.

import java.io.UnsupportedEncodingException; 
import java.math.BigInteger; 
import java.security.InvalidKeyException; 
import java.security.Key; 
import java.security.NoSuchAlgorithmException; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.crypto.BadPaddingException; 
import javax.crypto.Cipher; 
import javax.crypto.IllegalBlockSizeException; 
import javax.crypto.KeyGenerator; 
import javax.crypto.NoSuchPaddingException; 
import javax.crypto.SecretKey; 
import javax.crypto.spec.SecretKeySpec; 

public class StringDecryptor { 

    public static String encrypt(String text, String key) { 
     Key aesKey = null; 
     Cipher cipher = null; 
     byte[] encrypted = null; 
     try { 
      aesKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 
      cipher = Cipher.getInstance("AES"); 
      cipher.init(Cipher.ENCRYPT_MODE, aesKey); 
      encrypted = cipher.doFinal(text.getBytes()); 
     } catch (NoSuchAlgorithmException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (NoSuchPaddingException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (InvalidKeyException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (IllegalBlockSizeException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (BadPaddingException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (UnsupportedEncodingException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     return new String(encrypted); 
    } 

    public static String decrypt(String text, String key) { 
     Key aesKey = null; 
     Cipher cipher; 
     String decrypted = null; 
     try { 
      aesKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES"); 
      cipher = Cipher.getInstance("AES"); 
      cipher.init(Cipher.DECRYPT_MODE, aesKey); 
      decrypted = new String(cipher.doFinal(text.getBytes())); 
     } catch (NoSuchAlgorithmException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (NoSuchPaddingException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (InvalidKeyException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (IllegalBlockSizeException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (BadPaddingException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } catch (UnsupportedEncodingException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     return decrypted; 
    } 

    public static String generateKey() { 
     SecretKey secretKey = null; 
     try { 
      secretKey = KeyGenerator.getInstance("AES").generateKey(); 
     } catch (NoSuchAlgorithmException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     String keyString = bytesToString(secretKey.getEncoded()); 
     return keyString; 
    } 

    public static String bytesToString(byte[] b) { 
     String decoded = null; 
     try { 
      decoded = new String(b, "UTF-8");    
     } catch (UnsupportedEncodingException ex) { 
      Logger.getLogger(StringDecryptor.class.getName()).log(Level.SEVERE, null, ex); 
     } 
     return decoded; 
    } 

    public static void main(String args[]) { 
     String key = generateKey(); 
     System.out.println("key: " + key); 
     String str = "This is the original string..."; 
     String enc = encrypt(str, key); 
     System.out.println("enc: " + enc); 
     String dec = decrypt(enc, key); 
     System.out.println("dec: " + dec); 
    } 
} 

이 코드는 다음 예외를 throw합니다.

SEVERE: null 
java.security.InvalidKeyException: Invalid AES key length: 26 bytes 
    at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:372) 
    at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052) 
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1010) 
    at javax.crypto.Cipher.implInit(Cipher.java:786) 
    at javax.crypto.Cipher.chooseProvider(Cipher.java:849) 
    at javax.crypto.Cipher.init(Cipher.java:1213) 
    at javax.crypto.Cipher.init(Cipher.java:1153) 
    at com.innolabmm.software.luckydraw.utils.StringDecryptor.encrypt(StringDecryptor.java:27) 
    at com.innolabmm.software.luckydraw.utils.StringDecryptor.main(StringDecryptor.java:95) 

Exception in thread "main" java.lang.NullPointerException 
    at java.lang.String.<init>(String.java:556) 
    at com.innolabmm.software.luckydraw.utils.StringDecryptor.encrypt(StringDecryptor.java:42) 
    at com.innolabmm.software.luckydraw.utils.StringDecryptor.main(StringDecryptor.java:95) 
Java Result: 1 

AES 키 변환으로 인해 예외가 발생하지 않는 키 문자열을 생성하는 방법이 있습니까?

답변

0

AES는 길이가 128, 192 또는 256 비트 인 키가 필요합니다. 더 긴 키를 사용해보십시오.

+0

키가 생성되었을 때 키가 올바른 길이 였지만 암호화가 발생했을 때 키가 짧아 졌다고 생각합니다. –

1

AES- 알고리즘으로 암호화하려면 적어도 128 비트 문자열에 기반해야합니다.

는 128 8

128/8 = 16 alpha-numeric characters 

로 나눈 걸릴 수 있습니다 제공 키 - 문자열에서 필요한 문자 수로 그 변환하려면 (다른 값도 법적,하지만 난 내 머리를하지 않습니다) 이렇게하면 문제가 해결됩니다.

편집 : BASE64 문자열을 인코딩하는 다른 방법입니다 : BASE64에 대한 의견에

대답. BASE64 인코딩의 결과는 기본적으로 128 비트 문자열이 될 수 있지만 기본값은 아닙니다. 실제로 BASE64 인코딩 결과의 기본 길이는 없습니다. 결과는 8 자 또는 512 또는 BASE64의 인코딩 규칙을 따르는 다른 출력이 될 수 있습니다. 인코딩은 모두 인코딩하는 문자열에 따라 다릅니다. 여기

+0

Base64는 128 비트 문자열입니까? –

0

는 AES 키를 생성하는 작업 예입니다 :

private static SecretKeySpec key; 
private static final int ENCRYPTION_KEY_SIZE = 128; 

private static SecretKey generateKey() throws NoSuchAlgorithmException { 

KeyGenerator keyGenerator = null; 
keyGenerator = KeyGenerator.getInstance("AES"); 
keyGenerator.init(ENCRYPTION_KEY_SIZE); 

SecretKey key = keyGenerator.generateKey(); 
return key; 
} 

public void createNewEncrytionKey() throws NoSuchAlgorithmException, Exception { 
SecretKey newKey = generateKey(); 
saveKey(newKey); 
LogUtil.logMessage("createNewEncrytionKey", "New random encryption key was created.", logger); 
key = (SecretKeySpec) newKey; 
} 

당신이 다음 \ 암호화하는 그 키를 사용하여 내가 16 진하기 위해 암호화 된 값을 변환의 예에서 (코드를 해독 할 수 있습니다 형식 :

/** 
    * Encrypt a given text 
    * 
    * @param value String to encrypt 
    * @return encrypted String value 
    */ 
    public static String encrypt(String value) { 

    if (null == key) { 
     throw new RuntimeException("Secret encryption key not found!"); 
    } 

    Cipher c; 
    String result = null; 
    try { 
     c = Cipher.getInstance(ENCRYPTION_ALGORITHM); 
     c.init(Cipher.ENCRYPT_MODE, key); 
     // 1. convert value to byte array 
     byte[] bvalue = value.getBytes(); 
     // 2. convert to encrypted byte array 
     byte[] encrypted = c.doFinal(bvalue); 
     // 3. convert to hexadecimal representation 
     result = toHexString(encrypted); 
    } catch (Exception e) { 
     LogUtil.logError("encrypt", e, logger); 
    } 

    return result; 
    } 


/** 
    * Decrypt a given text 
    * 
    * @param value encrypted String value 
    * @return Decrypted value 
    */ 
    public static String decrypt(String value) { 

    if (null == key) { 
     throw new RuntimeException("Secret encryption key not found!"); 
    } 

    Cipher c; 
    String result = null; 
    try { 
     // 1. convert hex to encrypted byte array 
     byte[] encrypted = hexToByteArray(value); 
     // 2. convert to decrypted byte array 
     c = Cipher.getInstance(ENCRYPTION_ALGORITHM); 
     c.init(Cipher.DECRYPT_MODE, key); 
     byte[] decrypted = c.doFinal(encrypted); 
     // 3. convert to plain string 
     result = bytesToString(decrypted); 
    } catch (Exception e) { 
     LogUtil.logError("decrypt", e, logger); 
    } 

    return result; 
    } 
+0

문제는 암호화/해독에 관한 것이 아닙니다. 열쇠를 생성하고 그 열쇠를 어딘가에 저장하여 나중에 나중의 암호화 및 암호 해독 작업에 사용할 수 있습니다. –

0

문제는 AES 또는 암호화와 관련이 없습니다. 그러나 임의의 바이트 시퀀스를 UTF-8로 인코딩 된 문자로 해석하려고합니다 (b은 AES 키입니다) :

String decoded = new String(b, "UTF-8");

바이트 배열에 UTF-8에 대해 유효하지 않은 여러 바이트 시퀀스가 ​​포함될 가능성이 높으므로 작동하지 않습니다. 바이트 배열 내용의 문자열 표현이 필요하면 예를 들어를 사용하여 데이터를 인코딩해야합니다. base64 또는 16 진수 인코딩.

관련 문제