23 7월

C#, PHP – RIJNDAEL 256bit 암/복호화

C#과 php간에 데이터를 주고 받아야 하는데
평문으로 통신하기에 무리가 있던 도중
기존에 사용하던 php 암호화 라이브러리와 연동되는 c# 코드를 발견~
살짝 수정해서 사용하는데 무리가 없음

기본은 128bit지만 256bit로 변경했음
php의 경우 블록에서 남는 부분을 zero로 채워넣기 때문에
c#에서 PaddingMode.Zeros를 설정해야 정상적으로 동작합니다.

Encryption.cs

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

namespace TestClass
{
    class Encryption
    {
        private static byte[] rijnKey = Encoding.UTF8.GetBytes("abcdefg_abcdefg_");
        private static byte[] rijnIV = Encoding.UTF8.GetBytes("abcdefg_");

        public static String EncryptIt(String s)
        {
            String result;
            RijndaelManaged rijn = new RijndaelManaged();
            rijn.Mode = CipherMode.ECB;
            rijn.Padding = PaddingMode.Zeros; // php와의 연동에서 꼭 확인
            rijn.BlockSize = 256;

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (ICryptoTransform encryptor = rijn.CreateEncryptor(rijnKey, rijnIV))
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(s);
                        }
                    }
                }
                result = Convert.ToBase64String(msEncrypt.ToArray());
            }
            rijn.Clear();

			result = Base64UrlEncode(result);

			return result;
        }

        public static String DecryptIt(String s)
        {
            String result;
            RijndaelManaged rijn = new RijndaelManaged();
            rijn.Mode = CipherMode.ECB;
            rijn.Padding = PaddingMode.Zeros;
            rijn.BlockSize = 256;

            s = Base64UrlDecode(s);

            using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(s)))
            {
                using (ICryptoTransform decryptor = rijn.CreateDecryptor(rijnKey, rijnIV))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader swDecrypt = new StreamReader(csDecrypt))
                        {
                            result = swDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            rijn.Clear();

            return result;
        }

        public static string Base64UrlEncode(string arg)
        {
            arg = arg.Split('=')[0]; // Remove any trailing '='s
            arg = arg.Replace('+', '-'); // 62nd char of encoding
            arg = arg.Replace('/', '_'); // 63rd char of encoding
            return arg;
        }

        public static string Base64UrlDecode(string arg)
        {
            string s = arg;
            s = s.Replace('-', '+'); // 62nd char of encoding
            s = s.Replace('_', '/'); // 63rd char of encoding
            switch (s.Length % 4) // Pad with trailing '='s
            {
                case 0: break; // No pad chars in this case
                case 2: s += "=="; break; // Two pad chars
                case 3: s += "="; break; // One pad char
                default:
                    throw new System.Exception("Illegal base64url string!");
            }
            return s;
        }
    }
}

test.php

<?php
//Encryption function
function encryption($encrypt, $key, $iv)
{
    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_ECB, '');
    mcrypt_generic_init($td, $key, $iv);
    $encrypted = mcrypt_generic($td, $encrypt);
    $encode = base64_encode($encrypted);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

	return $encode;
}


//Decryption function
function decryption($decrypt, $key, $iv)
{
    $decoded = base64safeDecode($decrypt);
    $decoded = base64_decode($decoded);
    $td = mcrypt_module_open(MCRYPT_RIJNDAEL_256, '', MCRYPT_MODE_ECB, '');
    mcrypt_generic_init($td, $key, $iv);
    $decrypted = mdecrypt_generic($td, $decoded);
    mcrypt_generic_deinit($td);
    mcrypt_module_close($td);

    return trim($decrypted);
}

function base64safeDecode($data) {
	$data = str_replace("-", "+", $data);
	$data = str_replace("_", "/", $data);

	switch (strlen($data) % 4) {
		case 0: break;
		case 1: $data .= "=="; break;
		case 2: $data .= "="; break;
	}

	return $data;
}

$key = "abcdefg_abcdefg_";
$iv = "abcdefg_";

echo encryption("Hello world!", $key, $iv);
echo decryption("1ERpu8RaiyMqsXdjhCEu9IVMyQlz/A3fBR6vGbNxaVs=", $key, $iv);
?>

답글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.