C#, Java 간 암복호화를 사용할 일이 있어서 정리해봅니다.

처리 방법은 2가지가 있습니다.

1. TransformFinalBlock : 바이트 전체를 한번에 처리

2. CryptoStream : 스트림 단위로 잘라서 처리 1MB 이상이면 권장된다고 합니다!

using System;
using System.Security.Cryptography;
using System.Text;

namespace ConsoleApp1
{
    class Program
    {
        private static readonly string KEY = "0123456789abcdef0123456789abcdef"; // 32-byte
        private static readonly string IV = "abcdef9876543210"; // 16-byte

        private static Aes aes;

        static void Main(string[] args)
        {
            aes = Aes.Create();
            aes.Key = Encoding.UTF8.GetBytes(KEY); //CBC므로 32바이트
            aes.IV = Encoding.UTF8.GetBytes(IV); //16바이트 (첫 XOR 값)
            aes.Mode = CipherMode.CBC; //16바이트 단위로 XOR 처리
            aes.Padding = PaddingMode.PKCS7; //패딩 끝 부분 바이트 처리 (부족한 길이 반복)

            string originalText = "Hello, AES-256!";
            Console.WriteLine("Original: " + originalText);

            string encryptedText = Encrypt(originalText);
            Console.WriteLine("Encrypted: " + encryptedText);

            string decryptedText = Decrypt(encryptedText);
            Console.WriteLine("Decrypted: " + decryptedText);
        }

        static string Encrypt(string plainText)
        {
            ICryptoTransform encryptor = aes.CreateEncryptor();
            byte[] inputBytes = Encoding.UTF8.GetBytes(plainText);

            //****************************************************************
            //통 Block 방식
            byte[] encryptedBytes = encryptor.TransformFinalBlock(inputBytes, 0, inputBytes.Length);
            return Convert.ToBase64String(encryptedBytes); //통신용이라면 base64가 안전 (아니면 그냥 UTF8로 해도 괜찮습니다!)
            
            //****************************************************************
            //Stream 방식 (1MB 이상이면 스트림 방식 권장)
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    cs.Write(inputBytes, 0, inputBytes.Length);
                    cs.FlushFinalBlock();
                }
                return Convert.ToBase64String(ms.ToArray());
            }
        }

        static string Decrypt(string encryptedText)
        {
            ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
            byte[] encryptedBytes = Convert.FromBase64String(encryptedText); //Encrypt 후반에 base64를 썻는지에 따라 처리!
            
            //****************************************************************
            //통 Block 방식
            byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
            return Encoding.UTF8.GetString(decryptedBytes);
            //****************************************************************

            //Stream 방식 (1MB 이상이면 스트림 방식 권장)
            using (MemoryStream ms = new MemoryStream(encryptedBytes))
            {
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    using (MemoryStream result = new MemoryStream())
                    {
                        cs.CopyTo(result);
                        return Encoding.UTF8.GetString(result.ToArray());
                    }
                }
            }
        }
    }
}

 

 

 

C#가 호환되는 자바쪽 소스 (GPT가 알려준 소스..!)

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

public class Test {
    // 주어진 AES 256-bit (32-byte) Key와 16-byte IV
    private static final String KEY = "0123456789abcdef0123456789abcdef"; // 32-byte
    private static final String IV = "abcdef9876543210"; // 16-byte

    public static String encrypt(String plainText) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes());

        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
        byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));

        return Base64.getEncoder().encodeToString(encrypted);
    }

    public static String decrypt(String encryptedText) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        SecretKeySpec secretKey = new SecretKeySpec(KEY.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(IV.getBytes());

        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        byte[] decodedBytes = Base64.getDecoder().decode(encryptedText);
        byte[] decrypted = cipher.doFinal(decodedBytes);

        return new String(decrypted, "UTF-8");
    }

    public static void main(String[] args) {
        try {
            String originalText = "Hello, AES-256!";
            System.out.println("Original: " + originalText);

            String encryptedText = encrypt(originalText);
            System.out.println("Encrypted: " + encryptedText);

            String decryptedText = decrypt(encryptedText);
            System.out.println("Decrypted: " + decryptedText);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

+ Recent posts