FrameWork

[Unity] 프레임워크 개발 - 5. 암호화 ( 비대칭형 암호화 RSA )

EveryDay.DevUp 2020. 5. 5. 14:48

게임에서 사용하는 암호화를 실제 코드로 구현하여 프레임워크에 추가

자세한 이론은 하단의 링크를 참고

https://everyday-devup.tistory.com/24

 

[Unity] 게임 암호화

게임의 암호화는 유저의 데이터를 지키고, 게임을 서비스 하면서 안정적인 운영을 할 수 있도록 도와주는 것 ▶ 메모리 핵, 앱 변조, 스피드 핵, 데미지 핵과 같은 많은 핵들이 존재하고 방어하��

everyday-devup.tistory.com

Crypto Class를 생성 Static 으로 암복호화 함수 추가 

▶ 양방향 암호화 중 비대칭형 암호화는 RSA 를 사용

: RSA의 공개 키와 비밀 키를 파일로 저장해서 관리하기 위해 폴더 경로와 파일 이름을 추가

: 공개 키, 비밀 키 정보를 가질 수 있도록 변수 추가

public class CryptoComponent : MonoBehaviour
{
	[HideInInspector]
	public string folderPath = string.Empty;
	[HideInInspector]
	public string fileName = string.Empty;

	[HideInInspector]
	public string rsaBase64PublicKey = string.Empty;
	[HideInInspector]
	public string rsaBase64PrivateKey = string.Empty;
}

 : 공개 키, 비밀 키 암복호화 코드 

public class Crypto
{
    static Dictionary<string, CryptoRSA> _rsaManages = new Dictionary<string, CryptoRSA>();

	static void CreateRSAManage(string base64PublicKey, string base64PrivateKey)
	{
		CryptoRSA rsaManage = new CryptoRSA();
		rsaManage.Create( base64PublicKey, base64PrivateKey );
		_rsaManages.Add( base64PublicKey, rsaManage );
	}

	public static string EncryptRSAbyBase64PublicKey(string plainText, string base64PublicKey, string base64PrivateKey )
	{
		if( _rsaManages.ContainsKey( base64PublicKey ) == false )
		{
			CreateRSAManage( base64PublicKey, base64PrivateKey );
		}

		return _rsaManages[base64PublicKey].Encrypt( plainText );
	}

	public static string DecryptRSAByBase64Key(string encryptData, string base64PublicKey, string base64PrivateKey)
	{
		if( _rsaManages.ContainsKey( base64PublicKey ) == false )
		{
			CreateRSAManage( base64PublicKey, base64PrivateKey );
		}

		return _rsaManages[base64PublicKey].Decrypt( encryptData );
	}
}

: RSA 키 생성 및 저장/로드 기능 추가

using System.Security.Cryptography;
using System.Text;
using UnityEditor;
using UnityEngine;

[CustomEditor( typeof( CryptoComponent ) )]
public class CryptoEditor : Editor
{
	CryptoComponent _cryptoComponent;

	private void OnEnable()
	{
		_cryptoComponent = (CryptoComponent)target;
	}

	public override void OnInspectorGUI()
	{
		base.OnInspectorGUI();
        
		OnRsaUI();
	}

	void OnRsaUI()
	{
		EditorGUILayout.TextField( "RSA Base64 Public Key", _cryptoComponent.rsaBase64PublicKey );
		EditorGUILayout.TextField( "RSA Base64 Private Key", _cryptoComponent.rsaBase64PrivateKey );

		if( GUILayout.Button( "Create" ) )
		{
			RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();

			RSAParameters privateKeyParam = RSA.Create().ExportParameters( true );
			rsaCryptoServiceProvider.ImportParameters( privateKeyParam );
			string privateKey = rsaCryptoServiceProvider.ToXmlString( true );
			_cryptoComponent.rsaBase64PrivateKey = Crypto.EncodingBase64( privateKey );

			RSAParameters publicKeyParam = new RSAParameters();
			publicKeyParam.Modulus = privateKeyParam.Modulus;
			publicKeyParam.Exponent = privateKeyParam.Exponent;
			rsaCryptoServiceProvider.ImportParameters( publicKeyParam );
			string publicKey = rsaCryptoServiceProvider.ToXmlString( false );
			_cryptoComponent.rsaBase64PublicKey = Crypto.EncodingBase64( publicKey );

			EditorUtility.SetDirty( _cryptoComponent );
		}

		EditorGUILayout.BeginHorizontal();
		EditorGUILayout.TextField( "RSA Save/Load Path", _cryptoComponent.folderPath );
		if( GUILayout.Button( "Select" ) )
		{
			_cryptoComponent.folderPath = EditorUtility.OpenFolderPanel( "Select Folder", _cryptoComponent.folderPath, "" );
		}
		EditorGUILayout.EndHorizontal();

		_cryptoComponent.fileName = EditorGUILayout.TextField( "RSA FileName", _cryptoComponent.fileName );
		if( GUILayout.Button( "Save" ) )
		{
			string data = _cryptoComponent.rsaBase64PublicKey + "\n" + _cryptoComponent.rsaBase64PrivateKey;
			FileUtil.WriteFile( _cryptoComponent.folderPath, _cryptoComponent.fileName, ".txt", data, _cryptoComponent.aesBase64Key, _cryptoComponent.aesBase64IV );
		}

		if( GUILayout.Button( "Load" ) )
		{
			string data = FileUtil.ReadFile( _cryptoComponent.folderPath, _cryptoComponent.fileName, ".txt", _cryptoComponent.aesBase64Key, _cryptoComponent.aesBase64IV );
			string[] splitData = data.Split( '\n' );

			_cryptoComponent.rsaBase64PublicKey = splitData[0];
			_cryptoComponent.rsaBase64PrivateKey = splitData[1];
		}
	}
}