Programing

비밀 키를 문자열로 또는 그 반대로 변환

lottogame 2020. 9. 6. 11:49
반응형

비밀 키를 문자열로 또는 그 반대로 변환


키를 생성 중이며 DB에 저장해야하므로 문자열로 변환하지만 문자열에서 키를 다시 가져옵니다. 이를 수행하는 가능한 방법은 무엇입니까?

내 코드는

SecretKey key = KeyGenerator.getInstance("AES").generateKey();
String stringKey=key.toString();
System.out.println(stringKey);

문자열에서 키를 어떻게 되 찾을 수 있습니까?


SecretKey바이트 배열 ( byte[]) 로 변환 한 다음 Base64로 String. 다시 SecretKey, Base64 로 변환하려면 문자열을 디코딩하고 a SecretKeySpec에서 사용하여 원본을 다시 빌드합니다 SecretKey.

Java 8의 경우

문자열에 대한 SecretKey :

// create new key
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
// get base64 encoded version of the key
String encodedKey = Base64.getEncoder().encodeToString(secretKey.getEncoded());

SecretKey에 대한 문자열 :

// decode the base64 encoded string
byte[] decodedKey = Base64.getDecoder().decode(encodedKey);
// rebuild key using SecretKeySpec
SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); 

Java 7 이하 (Android 포함) :

참고 I : Base64 인코딩 / 디코딩 부분을 건너 뛰고 byte[]SQLite에 저장할 수 있습니다. 즉, Base64 인코딩 / 디코딩을 수행하는 것은 비용이 많이 드는 작업이 아니며 거의 모든 DB에 문제없이 문자열을 저장할 수 있습니다.

참고 II : 이전 Java 버전은 java.lang또는 java.util패키지 중 하나에 Base64를 포함하지 않습니다 . 그러나 Apache Commons Codec , Bouncy Castle 또는 Guava의 코덱을 사용할 수 있습니다 .

문자열에 대한 SecretKey :

// CREATE NEW KEY
// GET ENCODED VERSION OF KEY (THIS CAN BE STORED IN A DB)

    SecretKey secretKey;
    String stringKey;

    try {secretKey = KeyGenerator.getInstance("AES").generateKey();}
    catch (NoSuchAlgorithmException e) {/* LOG YOUR EXCEPTION */}

    if (secretKey != null) {stringKey = Base64.encodeToString(secretKey.getEncoded(), Base64.DEFAULT)}

SecretKey에 대한 문자열 :

// DECODE YOUR BASE64 STRING
// REBUILD KEY USING SecretKeySpec

    byte[] encodedKey     = Base64.decode(stringKey, Base64.DEFAULT);
    SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");

빠르게 실패 하는 일부 함수를 만드는 것이 얼마나 재미 있는지 보여주기 위해 다음 세 가지 함수를 작성했습니다.

하나는 AES 키를 만들고 하나는이를 인코딩하고 다른 하나는 다시 디코딩합니다. 이 세 가지 메소드는 Java 8에서 사용할 수 있습니다 (내부 클래스 또는 외부 종속성없이).

public static SecretKey generateAESKey(int keysize)
        throws InvalidParameterException {
    try {
        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
            // this may be an issue if unlimited crypto is not installed
            throw new InvalidParameterException("Key size of " + keysize
                    + " not supported in this runtime");
        }

        final KeyGenerator keyGen = KeyGenerator.getInstance("AES");
        keyGen.init(keysize);
        return keyGen.generateKey();
    } catch (final NoSuchAlgorithmException e) {
        // AES functionality is a requirement for any Java SE runtime
        throw new IllegalStateException(
                "AES should always be present in a Java SE runtime", e);
    }
}

public static SecretKey decodeBase64ToAESKey(final String encodedKey)
        throws IllegalArgumentException {
    try {
        // throws IllegalArgumentException - if src is not in valid Base64
        // scheme
        final byte[] keyData = Base64.getDecoder().decode(encodedKey);
        final int keysize = keyData.length * Byte.SIZE;

        // this should be checked by a SecretKeyFactory, but that doesn't exist for AES
        switch (keysize) {
        case 128:
        case 192:
        case 256:
            break;
        default:
            throw new IllegalArgumentException("Invalid key size for AES: " + keysize);
        }

        if (Cipher.getMaxAllowedKeyLength("AES") < keysize) {
            // this may be an issue if unlimited crypto is not installed
            throw new IllegalArgumentException("Key size of " + keysize
                    + " not supported in this runtime");
        }

        // throws IllegalArgumentException - if key is empty
        final SecretKeySpec aesKey = new SecretKeySpec(keyData, "AES");
        return aesKey;
    } catch (final NoSuchAlgorithmException e) {
        // AES functionality is a requirement for any Java SE runtime
        throw new IllegalStateException(
                "AES should always be present in a Java SE runtime", e);
    }
}

public static String encodeAESKeyToBase64(final SecretKey aesKey)
        throws IllegalArgumentException {
    if (!aesKey.getAlgorithm().equalsIgnoreCase("AES")) {
        throw new IllegalArgumentException("Not an AES key");
    }

    final byte[] keyData = aesKey.getEncoded();
    final String encodedKey = Base64.getEncoder().encodeToString(keyData);
    return encodedKey;
}

실제로 Luis가 제안한 것은 저에게 효과적이지 않았습니다. 나는 다른 방법을 찾아야했다. 이것이 나를 도왔습니다. 당신도 도울 수 있습니다. 연결:

  1. * .getEncoded () : https://docs.oracle.com/javase/7/docs/api/java/security/Key.html

  2. 인코더 정보 : https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Encoder.html

  3. 디코더 정보 : https://docs.oracle.com/javase/8/docs/api/java/util/Base64.Decoder.html

코드 조각 : 인코딩 :

String temp = new String(Base64.getEncoder().encode(key.getEncoded()));

디코딩 :

byte[] encodedKey = Base64.getDecoder().decode(temp);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "DES");

을 사용하고 싶지 않습니다 .toString().

Notice that SecretKey inherits from java.security.Key, which itself inherits from Serializable. So the key here (no pun intended) is to serialize the key into a ByteArrayOutputStream, get the byte[] array and store it into the db. The reverse process would be to get the byte[] array off the db, create a ByteArrayInputStream offf the byte[] array, and deserialize the SecretKey off it...

... or even simpler, just use the .getEncoded() method inherited from java.security.Key (which is a parent interface of SecretKey). This method returns the encoded byte[] array off Key/SecretKey, which you can store or retrieve from the database.

This is all assuming your SecretKey implementation supports encoding. Otherwise, getEncoded() will return null.

edit:

You should look at the Key/SecretKey javadocs (available right at the start of a google page):

http://download.oracle.com/javase/6/docs/api/java/security/Key.html

Or this from CodeRanch (also found with the same google search):

http://www.coderanch.com/t/429127/java/java/Convertion-between-SecretKey-String-or


Converting SecretKeySpec to String and vice-versa: you can use getEncoded() method in SecretKeySpec which will give byteArray, from that you can use encodeToString() to get string value of SecretKeySpec in Base64 object.

While converting SecretKeySpec to String: use decode() in Base64 will give byteArray, from that you can create instance for SecretKeySpec with the params as the byteArray to reproduce your SecretKeySpec.

String mAesKey_string;
SecretKeySpec mAesKey= new SecretKeySpec(secretKey.getEncoded(), "AES");

//SecretKeySpec to String 
    byte[] byteaes=mAesKey.getEncoded();
    mAesKey_string=Base64.encodeToString(byteaes,Base64.NO_WRAP);

//String to SecretKeySpec
    byte[] aesByte = Base64.decode(mAesKey_string, Base64.NO_WRAP);
    mAesKey= new SecretKeySpec(aesByte, "AES");

try this, it's work without Base64 ( that is included only in JDK 1.8 ), this code run also in the previous java version :)

private static String SK = "Secret Key in HEX";


//  To Encrupt

public static String encrypt( String Message ) throws Exception{

    byte[] KeyByte = hexStringToByteArray( SK);
    SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES");

    Cipher c = Cipher.getInstance("DES","SunJCE");
    c.init(1, k);
    byte mes_encrypted[] = cipher.doFinal(Message.getBytes());

    String MessageEncrypted = byteArrayToHexString(mes_encrypted);
    return MessageEncrypted;
}

//  To Decrypt

public static String decrypt( String MessageEncrypted )throws Exception{

    byte[] KeyByte = hexStringToByteArray( SK );
    SecretKey k = new SecretKeySpec(KeyByte, 0, KeyByte.length, "DES");

    Cipher dcr =  Cipher.getInstance("DES","SunJCE");
    dc.init(Cipher.DECRYPT_MODE, k);
    byte[] MesByte  = hexStringToByteArray( MessageEncrypted );
    byte mes_decrypted[] = dcipher.doFinal( MesByte );
    String MessageDecrypeted = new String(mes_decrypted);

    return MessageDecrypeted;
}

public static String byteArrayToHexString(byte bytes[]){

    StringBuffer hexDump = new StringBuffer();
    for(int i = 0; i < bytes.length; i++){
    if(bytes[i] < 0)
    {   
        hexDump.append(getDoubleHexValue(Integer.toHexString(256 - Math.abs(bytes[i]))).toUpperCase());
    }else
    {
        hexDump.append(getDoubleHexValue(Integer.toHexString(bytes[i])).toUpperCase());
    }
    return hexDump.toString();

}



public static byte[] hexStringToByteArray(String s) {

    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2)
    {   
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i+1), 16));
    }
    return data;

} 

참고URL : https://stackoverflow.com/questions/5355466/converting-secret-key-into-a-string-and-vice-versa

반응형