Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I convert a String to a SecretKey

I want to convert String to secretKey

public void generateCode(String keyStr){ 
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128); // 192 and 256 bits may not be available
// Generate the secret key specs.
secretKey skey=keyStr;  //How can I make the casting here
//SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
}

I try to use BASE64Decoder instead of secretKey, but I face a problem which is I cannot specify key length.

EDIT: I want to call this function from another place

 static public String encrypt(String message , String key , int keyLength) throws Exception {
     // Get the KeyGenerator
   KeyGenerator kgen = KeyGenerator.getInstance("AES");
    kgen.init(keyLength); // 192 and 256 bits may not be available
    // Generate the secret key specs.
     SecretKey skey = key; //here is the error
   byte[] raw = skey.getEncoded();
    SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
    // Instantiate the cipher
    Cipher cipher = Cipher.getInstance("AES");

    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    System.out.println("msg is" + message + "\n raw is" + raw);
    byte[] encrypted = cipher.doFinal(message.getBytes());
    String cryptedValue = new String(encrypted);
    System.out.println("encrypted string: " + cryptedValue);
    return cryptedValue;
}

If anybody could help, I'd be very thankful.

like image 983
palAlaa Avatar asked Dec 29 '10 03:12

palAlaa


People also ask

What is SecretKey in Java?

A secret key is the piece of information or parameter that is used to encrypt and decrypt messages. In Java, we have SecretKey an interface that defines it as a secret (symmetric) key. The purpose of this interface is to group (and provide type safety for) all secret key interfaces.

What are the advantage and disadvantage of secret key encryption?

One advantage of secret key encryption is the efficiency with which it takes a large amount of data and encrypts it quite rapidly. Symmetric algorithms can also be easily implemented at the hardware level. The major disadvantage of secret key encryption is that a single key is used for both encryption and decryption.


1 Answers

No integrity checks, for these particular reasons

  1. The need is not apparent from the use case.
  2. "AES/GCM/NoPadding" mode is only available from Java 7 onward
  3. It depends on the user if they want to deploy e.g. HMAC and/or AESCMAC (recommended).
  4. It would require an additional key at the minimum, and two full passes.

If you got an implementation of GCM mode at both sides - e.g. using Bouncy Castle on Java 6 - please go for it, as it is much more secure (as long as the "IV" is really unique). It should be really easy to change the implementation.

Implementation notes regarding encryption

  1. This implementation is not safe when used in an unrestricted client / server role because of padding oracle attacks (they require 128 tries per byte or lower, on average, independent of algorithm or key size). You will need to use a MAC, HMAC or Signature over the encrypted data, and verify it before decrypting to deploy it in client/server mode.
  2. Decrypt will return null if decryption fails. This can only indicate a padding exception, which should be adequately handled (did I warn about padding oracle attacks?)
  3. Invalid keys will be returned as InvalidArgumentException.
  4. All other security related exceptions are "swept under the table" as it means that the Java runtime environment is invalid. For example, supporting "UTF-8" and "AES/CBC/PKCS5Padding" is required for every Java SE implementation.

Some other notes

  1. Please don't try the opposite and insert bytes directly into the input string of the encrypt method (using new String(byte[]) for instance). The method may fail silently!
  2. Optimized for readability. Go for Base64 stream and CipherStream implementations if you rather prefer speed and better memory footprint.
  3. You need at least Java 6 SE or compatible to run this code.
  4. Encryption/decryption may fail for AES key sizes over 128 bit as you may need policy files for unrestricted encryption (available from Oracle)
  5. Beware of governmental regulations when exporting encryption.
  6. This implementation uses hex keys instead of base64 keys as they are small enough, and hex is just easier to edit/verify manually.
  7. Used hex and base64 encoding/decoding retrieved from the JDK, no external libraries needed whatsoever.
  8. Uber simple to use, but of course not very object oriented, no caching of object instances used in encrypt/decrypt. Refactor at will.

OK, here comes some code...

    public static String encrypt(final String plainMessage,
            final String symKeyHex) {
        final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex);

        final byte[] encodedMessage = plainMessage.getBytes(Charset
                .forName("UTF-8"));
        try {
            final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            final int blockSize = cipher.getBlockSize();

            // create the key
            final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

            // generate random IV using block size (possibly create a method for
            // this)
            final byte[] ivData = new byte[blockSize];
            final SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
            rnd.nextBytes(ivData);
            final IvParameterSpec iv = new IvParameterSpec(ivData);

            cipher.init(Cipher.ENCRYPT_MODE, symKey, iv);

            final byte[] encryptedMessage = cipher.doFinal(encodedMessage);

            // concatenate IV and encrypted message
            final byte[] ivAndEncryptedMessage = new byte[ivData.length
                    + encryptedMessage.length];
            System.arraycopy(ivData, 0, ivAndEncryptedMessage, 0, blockSize);
            System.arraycopy(encryptedMessage, 0, ivAndEncryptedMessage,
                    blockSize, encryptedMessage.length);

            final String ivAndEncryptedMessageBase64 = DatatypeConverter
                    .printBase64Binary(ivAndEncryptedMessage);

            return ivAndEncryptedMessageBase64;
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException(
                    "key argument does not contain a valid AES key");
        } catch (GeneralSecurityException e) {
            throw new IllegalStateException(
                    "Unexpected exception during encryption", e);
        }
    }

    public static String decrypt(final String ivAndEncryptedMessageBase64,
            final String symKeyHex) {
        final byte[] symKeyData = DatatypeConverter.parseHexBinary(symKeyHex);

        final byte[] ivAndEncryptedMessage = DatatypeConverter
                .parseBase64Binary(ivAndEncryptedMessageBase64);
        try {
            final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            final int blockSize = cipher.getBlockSize();

            // create the key
            final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");

            // retrieve random IV from start of the received message
            final byte[] ivData = new byte[blockSize];
            System.arraycopy(ivAndEncryptedMessage, 0, ivData, 0, blockSize);
            final IvParameterSpec iv = new IvParameterSpec(ivData);

            // retrieve the encrypted message itself
            final byte[] encryptedMessage = new byte[ivAndEncryptedMessage.length
                    - blockSize];
            System.arraycopy(ivAndEncryptedMessage, blockSize,
                    encryptedMessage, 0, encryptedMessage.length);

            cipher.init(Cipher.DECRYPT_MODE, symKey, iv);

            final byte[] encodedMessage = cipher.doFinal(encryptedMessage);

            // concatenate IV and encrypted message
            final String message = new String(encodedMessage,
                    Charset.forName("UTF-8"));

            return message;
        } catch (InvalidKeyException e) {
            throw new IllegalArgumentException(
                    "key argument does not contain a valid AES key");
        } catch (BadPaddingException e) {
            // you'd better know about padding oracle attacks
            return null;
        } catch (GeneralSecurityException e) {
            throw new IllegalStateException(
                    "Unexpected exception during decryption", e);
        }
    }

Usage:

    String plain = "Zaphod's just zis guy, ya knöw?";
    String encrypted = encrypt(plain, "000102030405060708090A0B0C0D0E0F");
    System.out.println(encrypted);
    String decrypted = decrypt(encrypted, "000102030405060708090A0B0C0D0E0F");
    if (decrypted != null && decrypted.equals(plain)) {
        System.out.println("Hey! " + decrypted);
    } else {
        System.out.println("Bummer!");
    }
like image 137
Maarten Bodewes Avatar answered Oct 04 '22 16:10

Maarten Bodewes