~/home of geeks

Symmetrische Verschlüsselung

· 829 Wörter · 4 Minute(n) Lesedauer

Bei der symmetrischen Verschlüsselung teilen sich zwei Kommunikationspartner einen geheimen Schlüssel (Passwort). Die folgende einfache Javaklasse hilft dabei, die Ver- und Entschlüsselung durchzuführen.

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

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;

/**
 * Hilfsklasse für symmetrische Verschlüsselungen.
 * 
 * @author Serhat Cinar
 */
public final class CryptionUtils {
    /**
     * Bezeichner AES.
     */
    public static final String ALGO_AES = "AES";
    /**
     * Bezeichner DES.
     */
    public static final String ALGO_DES = "DES";
    /**
     * Bezeichner Tripple-DES.
     */
    public static final String ALGO_TRIPPLE_DES = "DESede";
    /**
     * Bezeichner Blowfish.
     */
    public static final String ALGO_BLOWFISH = "Blowfish";

    private CryptionUtils() {
    }

    /**
     * Verschlüsselt die angegebenen Daten mit dem angegebenen Schlüssel.
     * 
     * @param algorithm Ein Verschlüsselungsalgortihmus, z. B. "DES"
     * @param secretKey Der Schlüssel
     * @param rawData Zu verschlüsselnde Daten
     * @return Verschlüsselte Daten
     */
    public static final byte[] encryptSymmetric(final String algorithm, final byte[] secretKey, final byte[] rawData)
        throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException,
        BadPaddingException {
        final SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, algorithm);
        final Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        return cipher.doFinal(rawData);
    }

    /**
     * Verschlüsselt die angegebenen Daten mit dem angegebenen Schlüssel.
     * 
     * @param algorithm Ein Verschlüsselungsalgortihmus, z. B. "DES"
     * @param secretKeyHex Der Schlüssel als HEX-String
     * @param rawData Zu verschlüsselnde Daten
     * @return Verschlüsselte Daten
     */
    public static final byte[] encryptSymmetric(final String algorithm, final String secretKeyHex, final String rawData)
        throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException,
        BadPaddingException, UnsupportedEncodingException {
        final SecretKeySpec secretKeySpec = new SecretKeySpec(hexStringToByteArray(secretKeyHex), algorithm);
        final Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        return cipher.doFinal(rawData.getBytes("UTF-8"));
    }

    /**
     * Entschlüsselt die angegebenen Daten mit dem angegebenen Schlüssel.
     * 
     * @param algorithm Ein Verschlüsselungsalgortihmus, z. B. "DES"
     * @param secretKey Der Schlüssel
     * @param encryptedData Verschlüsselte Daten
     * @return Entschlüsselte Daten
     */
    public static final byte[] decryptSymmetric(final String algorithm, final byte[] secretKey,
        final byte[] encryptedData) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
        IllegalBlockSizeException, BadPaddingException {
        final SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey, algorithm);
        final Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        return cipher.doFinal(encryptedData);
    }

    /**
     * Entschlüsselt die angegebenen Daten mit dem angegebenen Schlüssel.
     * 
     * @param algorithm Ein Verschlüsselungsalgortihmus, z. B. "DES"
     * @param secretKeyHex Der Schlüssel als HEX-String
     * @param encryptedDataHex Verschlüsselte Daten als HEX-String
     * @return Entschlüsselte Daten
     */
    public static final byte[] decryptSymmetric(final String algorithm, final String secretKeyHex,
        final String encryptedDataHex) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
        IllegalBlockSizeException, BadPaddingException {
        final SecretKeySpec secretKey = new SecretKeySpec(hexStringToByteArray(secretKeyHex), algorithm);
        final Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        return cipher.doFinal(hexStringToByteArray(encryptedDataHex));
    }

    /**
     * Erzeugt einen Schlüssel.
     * 
     * @param algorithm Ein Verschlüsselungsalgortihmus, z. B. "DES"
     * @param keylength Länge des Schlüssels
     * @return Generierter Schlüssel
     */
    public static final byte[] generateSecretKey(final String algorithm, final int keylength)
        throws NoSuchAlgorithmException {
        final KeyGenerator keygen = KeyGenerator.getInstance(algorithm);
        keygen.init(keylength);
        final SecretKey secretKey = keygen.generateKey();
        return secretKey.getEncoded();
    }

    /**
     * Wandelt einen HEX-String in einen Byte-Array um.
     * 
     * @param s Ein HEX-String
     * @return Bytes aus dem HEX-String
     */
    public static final byte[] hexStringToByteArray(final String s) {
        final int len = s.length();
        final 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;
    }

    private static final String HEXES = "0123456789ABCDEF";


    /**
     * Wandelt einen Byte-Array in einen HEX-String um.
     * 
     * @param s Ein Byte-Array
     * @return HEX-String des Byte-Arrays
     */
    public static final String byteArrayToHexString(final byte[] raw) {
        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 final void main(final String argv[]) {
        boolean printUsage = true;
        if (argv != null && argv.length > 1) {
            final String action = argv[0];
            if ("keygen".equalsIgnoreCase(action) && argv.length >= 3) {
                final String algo = argv[1];
                int keyLength;
                try {
                    keyLength = Integer.parseInt(argv[2]);
                    System.out.println(byteArrayToHexString(generateSecretKey(algo, keyLength)));
                    printUsage = false;
                } catch (final Exception e) {
                    e.printStackTrace();
                }
            } else if ("encrypt".equalsIgnoreCase(action) && argv.length >= 4) {
                final String algo = argv[1];
                final String key = argv[2];
                final String data = argv[3];
                try {
                    System.out.println(byteArrayToHexString(encryptSymmetric(algo, key, data)));
                    printUsage = false;
                } catch (final Exception e) {
                    e.printStackTrace();
                }
            } else if ("decrypt".equalsIgnoreCase(action)) {
                final String algo = argv[1];
                final String key = argv[2];
                final String data = argv[3];
                try {
                    System.out.println(new String(decryptSymmetric(algo, key, data), "UTF-8"));
                    printUsage = false;
                } catch (final Exception e) {
                    e.printStackTrace();
                }
            }

        }
        if (printUsage) {
            printUsage();
            System.exit(0);
        }
    }

    private static void printUsage() {
        System.out.println("Usage: <action> <parameter>");
        System.out.println("  Actions:");
        System.out.println("    keygen - generates a key");
        System.out.println("     parameters: <algorithm> <keylength>");
        System.out.println("    encrypt - encrypts a text");
        System.out.println("     parameters: <algorithm> <hexsecretkey> <text>");
        System.out.println("    decrypt - decrypts a hex encoded secret");
        System.out.println("     parameters: <algorithm> <hexsecretkey> <hexdata>");
        System.out.println("  Algorithm should be one of \"" + ALGO_AES + "\", \"" + ALGO_BLOWFISH + "\", \""
            + ALGO_DES + "\", \"" + ALGO_TRIPPLE_DES + "\"");
        System.out.println("Examples:");
        System.out.println("\"keygen AES 128\" generates a key and prints it as hex-encoded");
    }
}