このエントリーをはてなブックマークに追加

java 暗号化

暗号化と複合化のサンプルクラス

package com.snowsaber.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class AesCbcUtil {
    
    private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
    
    /**
     * 16進数文字列をバイト配列に変換
     */
    private static byte[] hexToBytes(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                                 + Character.digit(hex.charAt(i+1), 16));
        }
        return data;
    }
    
    /**
     * AES-CBC復号化
     *
     * @param encryptedText Base64エンコードされた暗号化文字列
     * @param key 暗号化キー(16進数文字列)
     * @param iv 初期化ベクトル(16進数文字列)
     * @return 復号化された文字列
     */
    public static String decrypt(String encryptedText, String key, String iv) {
        try {
            byte[] keyBytes = hexToBytes(key);
            byte[] ivBytes = hexToBytes(iv);
            
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
            
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
            
            byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("Decryption failed", e);
        }
    }
    
    /**
     * AES-CBC暗号化
     *
     * @param plainText 平文
     * @param key 暗号化キー(16進数文字列)
     * @param iv 初期化ベクトル(16進数文字列)
     * @return Base64エンコードされた暗号化文字列
     */
    public static String encrypt(String plainText, String key, String iv) {
        try {
            byte[] keyBytes = hexToBytes(key);
            byte[] ivBytes = hexToBytes(iv);
            
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
            
            Cipher cipher = Cipher.getInstance(ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
            
            byte[] encryptedBytes = cipher.doFinal(plainText.getBytes());
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new RuntimeException("Encryption failed", e);
        }
    }
}

動作確認用のテストケース

package com.snowsaber.util;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class AesCbcUtilTest {

    // 16進数文字列形式のキーとIV(32文字 = 16バイト)
    private static final String KEY = "0123456789ABCDEF0123456789ABCDEF";
    private static final String IV = "FEDCBA9876543210FEDCBA9876543210";

    @Test
    void testEncryptAndDecrypt() {
        String originalText = "Hello, World!";
        
        // 暗号化
        String encrypted = AesCbcUtil.encrypt(originalText, KEY, IV);
        assertNotNull(encrypted);
        
        // 復号化
        String decrypted = AesCbcUtil.decrypt(encrypted, KEY, IV);
        assertEquals(originalText, decrypted);
    }

    @Test
    void testDecryptWithInvalidKey() {
        String encrypted = AesCbcUtil.encrypt("Test", KEY, IV);
        assertThrows(RuntimeException.class, () -> {
            // 不正なキー(16進数形式)
            AesCbcUtil.decrypt(encrypted, "00112233445566778899AABBCCDDEEFF", IV);
        });
    }
}