C#을 이용한 자동화 보안을 위한 간단한 암호화 기법(Enhancing Automation Security with Simple Encryption Techniques)
2024. 6. 12. 11:58ㆍDevelopment👩🏻🦳/C#

[예제 3] 1차원 배열을 이용한 N글자 전치암호 프로그.zip
0.04MB
암호화리팩토링.zip
0.04MB
암호화의 필요성 및 용도 ( Necessity and purpose of encryption )

공정 자동화에서 암호화 및 데이터 섞기 기술은 데이터 보호, 안전한 통신, 프로세스 보안 등 다양한 목적으로 사용됩니다.
1. 데이터 보호 및 기밀성 유지
- 생산 데이터 보호: 생산량, 공정 시간, 품질 검사 결과 등의 데이터를 암호화하여 보호.
- 기계 간 안전한 통신: 기계 간 통신 데이터를 암호화하여 도청 방지.
2. 데이터 무결성 및 인증
- 데이터 무결성 검증: 데이터 전송 중 변조 여부 확인.
- 사용자 인증 및 접근 제어: 사용자 인증 시 암호화된 토큰 사용.
3. 프로세스 보안 및 이상 감지
- 프로세스 보안 강화: 암호화된 명령어로 특정 프로세스 보호.
- 이상 감지 시스템: 암호화된 데이터를 통해 비정상 활동 탐지.
4. 공급망 보안
- 공급망 내 데이터 보호: 공급망 전체에서 데이터 암호화.
5. 원격 모니터링 및 제어
- 원격 제어 시스템 보호: 원격 모니터링 및 제어 시 데이터 암호화.
암호화 방식
현재 구현된 암호화 방식은 기본적인 단순 치환 암호화입니다. 이는 각 문자를 특정 규칙에 따라 다른 문자로 대체하는 방식입니다. 향후 다중 치환 암호화, 블록 암호화, 대칭 키 암호화, 비대칭 키 암호화, 양자 암호화 등의 고급 암호화 기법 도입이 필요합니다.

ASCII 코드를 이용한 간단한 암호화 예제
ASCII 코드를 활용한 암호화는 문자 데이터를 숫자로 변환하는 기본적인 과정을 통해 암호화의 기초를 제공합니다.
예제 코드: C#
csharp코드 복사
char c = 'A'; // 문자 'A'
int asciiValue = (int)c; // ASCII 코드 값 65
char newChar = (char)asciiValue; // 다시 문자 'A'로 변환
Console.WriteLine(asciiValue); // 출력: 65
Console.WriteLine(newChar); // 출력: A
핵심 구현 과정 요약
1. 입력 유효성 검사
csharp코드 복사
if (textBox1.Text == "") { /* 경고 1 */ }
if (textBox4.Text == "") { /* 경고 2 */ }
if (textBox5.Text == "") { /* 경고 3 */ }
if (int.Parse(textBox4.Text) < 2 || int.Parse(textBox4.Text) > 7) { /* 경고 4 */ }
if (int.Parse(textBox4.Text) != textBox5.Text.Length) { /* 경고 5 */ }
2. 섞을 순서 유효성 검사
csharp코드 복사
for (int j = 0; j < iCutting_Giri; j++) {
int iTemp = Convert.ToInt16(sSunceo[j]);
if (iTemp < 1 || iTemp > iCutting_Giri) { /* 경고 6 */ }
for (int k = j + 1; k < iCutting_Giri; k++) {
if (sSunceo[j] == sSunceo[k]) { /* 경고 7 */ }
}
}
// Check for three consecutive numbers in sequence
bool consecutiveFound = false;
for (int i = 0; i < iCutting_Giri - 2; i++) {
int a = Convert.ToInt16(sSunceo[i]);
int b = Convert.ToInt16(sSunceo[i + 1]);
int c = Convert.ToInt16(sSunceo[i + 2]);
if ((b == a + 1 && c == b + 1) || (b == a - 1 && c == b - 1)) {
consecutiveFound = true;
break;
}
}
if (consecutiveFound) {
/* 경고 9 */
}
3. 문자열을 정수로 변환 및 유효성 검사
csharp코드 복사
for (int iCount = 0; iCount < iMunjang_Giri; iCount++) {
sTemp = textBox1.Text.Substring(iCount, 1);
char cTemp = Convert.ToChar(sTemp);
int iTemp = Convert.ToInt32(cTemp);
if (iTemp < 97 || (iTemp > 122 && iTemp < 40000)) { /* 경고 10 */ }
}
4. 패딩 작업
csharp코드 복사
if (iMunjang_Giri % iCutting_Giri != 0) {
int iPadding_Giri = iCutting_Giri - (iMunjang_Giri % iCutting_Giri);
sTemp = textBox1.Text.Substring(iMunjang_Giri - 1, 1);
char cTemp = Convert.ToChar(sTemp);
int iTemp = Convert.ToInt32(cTemp);
if (iTemp > 96 && iTemp < 123)
textBox1.Text += sEng_Pad.Substring(0, iPadding_Giri);
else
textBox1.Text += sKor_Pad.Substring(0, iPadding_Giri);
}
5. 문자열 섞기 및 암호문 생성
csharp코드 복사
for (int j = 0; j < iMunjang_Giri; j += iCutting_Giri) {
for (int k = 0; k < iCutting_Giri; k++)
sTempArray[k] = sMunjang[j + k];
for (int y = 0; y < iCutting_Giri; y++)
sMunjang[j + y] = sTempArray[Convert.ToInt16(sSunceo[y]) - 1];
}
textBox2.Text = "";
for (int iCount = 0; iCount < iMunjang_Giri; iCount++) {
char cTemp = Convert.ToChar(sMunjang[iCount]);
int iTemp = Convert.ToInt32(cTemp);
if (iTemp > 96 && iTemp < 123)
textBox2.Text += Convert.ToChar(iTemp - (97 - 65));
else
textBox2.Text += sMunjang[iCount];
}
암호화 예제 코드
csharp코드 복사
using System;
using System.Text;
public class SimpleEncryption {
public static string Encrypt(string plainText, string key) {
char[] chars = plainText.ToCharArray();
int[] order = Array.ConvertAll(key.ToCharArray(), c => (int)char.GetNumericValue(c) - 1);
StringBuilder encrypted = new StringBuilder();
for (int i = 0; i < chars.Length; i += order.Length) {
char[] segment = new char[order.Length];
for (int j = 0; j < order.Length; j++) {
if (i + j < chars.Length) {
segment[order[j]] = chars[i + j];
} else {
segment[order[j]] = ' '; // Padding with spaces
}
}
encrypted.Append(segment);
}
return encrypted.ToString();
}
public static void Main() {
string plainText = "hellothere";
string key = "312";
string encryptedText = Encrypt(plainText, key);
Console.WriteLine("Encrypted: " + encryptedText);
}
}

해킹(복호화) 코드 예제
csharp코드 복사
using System;
using System.Text;
public class SimpleDecryption {
public static string Decrypt(string encryptedText, string key) {
char[] chars = encryptedText.ToCharArray();
int[] order = Array.ConvertAll(key.ToCharArray(), c => (int)char.GetNumericValue(c) - 1);
int[] reverseOrder = new int[order.Length];
// Creating reverse order
for (int i = 0; i < order.Length; i++) {
reverseOrder[order[i]] = i;
}
StringBuilder decrypted = new StringBuilder();
for (int i = 0; i < chars.Length; i += order.Length) {
char[] segment = new char[order.Length];
for (int j = 0; j < order.Length; j++) {
if (i + j < chars.Length) {
segment[j] = chars[i + reverseOrder[j]];
}
}
decrypted.Append(segment);
}
return decrypted.ToString();
}
public static void Main() {
string encryptedText = "elho htleer"; // Encrypted form of "hellothere" with key "312"
string key = "312";
string decryptedText = Decrypt(encryptedText, key);
Console.WriteLine("Decrypted: " + decryptedText);
}
}
코드 설명
- Encrypt 함수:
- 평문(plainText)과 키(key)를 입력으로 받아 암호화된 텍스트를 반환합니다.
- 키를 통해 문자의 순서를 결정하고, 해당 순서에 맞춰 문자를 재배열합니다.
- 문자 길이보다 짧은 경우 공백으로 패딩합니다.
- Decrypt 함수:
- 암호화된 텍스트(encryptedText)와 키(key)를 입력으로 받아 복호화된 텍스트를 반환합니다.
- 키를 통해 문자의 원래 순서를 결정하는 reverseOrder 배열을 생성합니다.
- 원래 순서에 따라 문자를 재배열하여 복호화된 텍스트를 생성합니다.
ASCII 코드 활용
- Convert.ToInt16 및 char.GetNumericValue를 사용하여 문자 데이터를 숫자로 변환합니다.
- StringBuilder를 사용하여 결과 문자열을 효율적으로 조립합니다.
장단점
장점
- 간단한 이해: 기본적인 암호화 및 복호화 개념을 쉽게 이해할 수 있습니다.
- ASCII 코드 활용: 문자 데이터를 처리하는 방법을 이해할 수 있습니다.
단점
- 보안 수준 낮음: 매우 단순한 암호화 방법으로, 현대적인 보안 요구사항을 충족하지 못합니다.
- 실제 적용의 한계: 학습 목적 외에 실무에서는 사용되지 않습니다.
비효율성 및 개선점
- goto 문 사용: 제어 구조를 통해 예외 처리 개선.
- 순서 검사: 중복 검사를 최소화.
- 사용자 입력 검사: 함수를 통한 코드 간결화.
- 하드코딩된 패딩 문자: 유연성 증대.

개선된 예시: Strategy 패턴 적용
인터페이스 정의
csharp코드 복사
public interface IEncryptionStrategy {
string Encrypt(string plainText, int segmentLength, string shuffleOrder);
}
단순 전치 암호화 전략 구현
csharp코드 복사
public class SimpleTranspositionEncryption : IEncryptionStrategy {
public string Encrypt(string plainText, int segmentLength, string shuffleOrder) {
// 패딩 처리
plainText = PadPlainText(plainText, segmentLength);
// 평문을 세그먼트로 나눔
string[] segments = SplitTextIntoSegments(plainText, segmentLength);
// 세그먼트를 섞음
string[] shuffledSegments = ShuffleSegments(segments, shuffleOrder);
// 암호문 생성
return CreateCipherText(shuffledSegments);
}
private string PadPlainText(string plainText, int segmentLength) {
int paddingLength = segmentLength - (plainText.Length % segmentLength);
if (paddingLength < segmentLength) {
char paddingChar = plainText[plainText.Length - 1] < 128 ? 'x' : '하';
plainText += new string(paddingChar, paddingLength);
}
return plainText;
}
private string[] SplitTextIntoSegments(string text, int segmentLength) {
int segmentCount = text.Length / segmentLength;
string[] segments = new string[segmentCount];
for (int i = 0; i < segmentCount; i++) {
segments[i] = text.Substring(i * segmentLength, segmentLength);
}
return segments;
}
private string[] ShuffleSegments(string[] segments, string shuffleOrder) {
string[] shuffledSegments = new string[segments.Length];
for (int i = 0; i < segments.Length; i++) {
char[] shuffledSegment = new char[segments[i].Length];
for (int j = 0; j < segments[i].Length; j++) {
shuffledSegment[j] = segments[i][shuffleOrder[j] - '1'];
}
shuffledSegments[i] = new string(shuffledSegment);
}
return shuffledSegments;
}
private string CreateCipherText(string[] segments) {
string cipherText = string.Join("", segments);
return cipherText.ToUpper();
}
}
Form1 클래스의 수정
csharp코드 복사
public partial class Form1 : Form {
private IEncryptionStrategy encryptionStrategy;
public Form1() {
InitializeComponent();
encryptionStrategy = new SimpleTranspositionEncryption();
}
private void buttonEncrypt_Click(object sender, EventArgs e) {
if (IsValidInput()) {
string cipherText = encryptionStrategy.Encrypt(
textBoxPlain.Text,
int.Parse(textBoxSegmentLength.Text),
textBoxShuffleOrder.Text
);
textBoxCipher.Text = cipherText;
}
}
private bool IsValidInput() {
if (string.IsNullOrEmpty(textBoxPlain.Text)) {
ShowError("평문을 입력하고 버튼을 누르세요.", "[ 경고 1 ]");
textBoxPlain.Focus();
return false;
}
if (string.IsNullOrEmpty(textBoxSegmentLength.Text)) {
ShowError("나눌 길이를 입력하고서 버튼을 누르세요.", "[ 경고 2 ]");
textBoxSegmentLength.Focus();
return false;
}
if (string.IsNullOrEmpty(textBoxShuffleOrder.Text)) {
ShowError("섞을 순서를 입력하고서 버튼을 누르세요.", "[ 경고 3 ]");
textBoxShuffleOrder.Focus();
return false;
}
if (!int.TryParse(textBoxSegmentLength.Text, out int segmentLength) || segmentLength < 2 || segmentLength > 7) {
ShowError("나눌 길이는 2~7 사이의 값입니다.", "[ 경고 4 ]");
textBoxSegmentLength.Focus();
textBoxSegmentLength.SelectAll();
return false;
}
if (textBoxShuffleOrder.Text.Length != segmentLength) {
ShowError("나눌 길이와 섞을 순서의 길이가 일치하지 않습니다.", "[ 경고 5 ]");
textBoxShuffleOrder.Focus();
textBoxShuffleOrder.SelectAll();
return false;
}
if (!IsValidShuffleOrder(textBoxShuffleOrder.Text, segmentLength)) {
return false;
}
return true;
}
private void ShowError(string message, string title) {
MessageBox.Show(message, title);
}
private bool IsValidShuffleOrder(string shuffleOrder, int segmentLength) {
bool[] isUsed = new bool[segmentLength];
for (int i = 0; i < segmentLength; i++) {
if (!int.TryParse(shuffleOrder[i].ToString(), out int order) || order < 1 || order > segmentLength) {
ShowError("섞을 순서는 1보다 작거나 나눌 길이보다 클 수 없습니다.", "[ 경고 6 ]");
textBoxShuffleOrder.Focus();
textBoxShuffleOrder.SelectionStart = i;
textBoxShuffleOrder.SelectionLength = 1;
return false;
}
if (isUsed[order - 1]) {
ShowError("동일한 순서가 두번 입력되었습니다", "[ 경고 7 ]");
textBoxShuffleOrder.Focus();
textBoxShuffleOrder.SelectionStart = i;
textBoxShuffleOrder.SelectionLength = 1;
return false;
}
isUsed[order - 1] = true;
}
return true;
}
}
이 접근 방식은 암호화 개념의 기초를 이해하는 데 유용하지만, 실제 보안 애플리케이션에는 더 강력한 암호화 알고리즘이 필요합니다.