'C#/Problems'에 해당되는 글 6건

  1. 2019.04.10 암호화하여 직렬화, 복호화하여 역직렬화 [문제해결중]
  2. 2019.04.01 멀티스레딩 + SetCursorPosition에서 생긴 문제 [해결]
  3. 2019.04.01 하는중
  4. 2019.03.28 공부할 것과 정리중인 것
  5. 2019.03.27 공부중
  6. 2019.03.25 Console.Read() 의 형변환 [해결]

암호화하여 직렬화, 복호화하여 역직렬화 [문제해결중]

C#/Problems 2019. 4. 10. 03:26



BinaryFormatter와 FileStream을 이용하여 Serialize, Deserialize까지는 무난하게 구현했다.

후에 AES-128 암호화 방식을 이용하여 암호화된 값으로 직렬화를 하고, 복호화를 이용하여 역직렬화해서 파일로는 값을 못보고, 내부에서만 사용할 수 있게끔 만드려고 했다.

처음에는 AES-128을 API를 이용하지 않고 구현하려고 했으나, AES 알고리즘 과정 중 SubByte(State Array의 값들을 S-Box의 값과 치환하는 과정)에서 막혀서 API를 이용했다.

암호화까지에는 성공했으나, 복호화 과정에서 지속적으로 스트림에서 오류가 발생했다.

위처럼 Deserialize하는 스트림이 계속 비어있다고 뜨는데, 도무지 해답을 찾지 못하겠다. (이건 아마 내가 Stream에 대한 지식이 부족한 것 같다)

국내 사이트부터 외국 사이트, Docs, 논문 다 봤는데 모르겠다.


string형으로도 받아보고, byte[]형으로도 받아보려했으나, 자꾸 저 에러가 뜬다.

내일은 stream 공부 더해보고 오류 수정해야겠다. 이젠 진짜 자야겠다.

내일 늦으면 안되는데




AES만드려고 작성하던 Backup.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
 
namespace TestMin
{
    public static class Backup
    {
        //Serialize Method
        public static bool Serialize<T>(T obj, string path)
        {
            if (obj == null)
            {
                return false;
            }
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            FileStream fileStream = new FileStream(path, FileMode.Create);
            binaryFormatter.Serialize(fileStream, obj);
            fileStream.Close();
            return true;
        }
 
        //Deserialize Method
        public static T Deserialize<T>(string path)
        {
            var isExists = File.Exists(path);
            if (isExists)
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                FileStream fileStream = new FileStream(path, FileMode.Open);
                var temp = binaryFormatter.Deserialize(fileStream);
                fileStream.Close();
                return (T)temp;
            }
            else
            {
                return default(T);
            }
        }
 
        //AES-256 Encryption
        public static void EncryptionToAES<T>(T obj)
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            MemoryStream memoryStream = new MemoryStream();
            binaryFormatter.Serialize(memoryStream, obj);
            byte[,] keyArr = new byte[44]
            {
                {0x540x4B0x200x53 },
                {0x480x490x4D0x45 },
                {0x450x4E0x490x4F },
                {0x200x470x4E0x4B }
            };
            var plainText = memoryStream.ToArray();
            byte[,] stateArr = new byte[44]
            {
                {plainText[0], plainText[4], plainText[8], plainText[12] },
                {plainText[1], plainText[5], plainText[9], plainText[13] },
                {plainText[2], plainText[6], plainText[10], plainText[14] },
                {plainText[3], plainText[7], plainText[11], plainText[15] }
            };
        }
 
        //State sub S-Box
        public static void SubByte()
        {
 
        }
 
        //Take Round Key
        public static void KeyExpansion()
        {
 
        }
 
        //ShiftRow
        public static void ShiftRow(byte[] state)
        {
            for (int row = 1; row < 4; row++//row1 ~ row3
            {
                //byte[1] temp 
            }
        }
 
        public static void KeySchedule()
        {
            //4의 배수
            //Key 4열 추출
 
            //1칸 Shift
 
            //S-Box와 치환
 
            //Key+1열에서 -4열 추출
 
            //-4열 XOR 치환열 XOR RCON
 
        }
 
        public static void MixColumn()
        {
            //(a(0,0)*02) XOR (a(1,0)*03) XOR (a(2,0)*01) XOR (a(3,0)*01)
        }
    }
}
 
cs




직렬화, 역직렬화, 암호화, 복호화

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Runtime.Serialization;
 
namespace TestMin
{
    public static class Minseok
    {
        //Serialize Method
        public static bool Serialize<T>(T obj, string path)
        {
            if (obj == null)
            {
                return false;
            }
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            FileStream fileStream = new FileStream(path, FileMode.Create);
            binaryFormatter.Serialize(fileStream, obj);
            fileStream.Close();
            return true;
        }
 
        //Deserialize Method
        public static T Deserialize<T>(string path)
        {
            var isExists = File.Exists(path);
            if (isExists)
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                FileStream fileStream = new FileStream(path, FileMode.Open);
                var temp = binaryFormatter.Deserialize(fileStream);
                fileStream.Close();
                return (T)temp;
            }
            else
            {
                return default(T);
            }
        }
 
        //AES-128 Encryption
        public static byte[] EncryptionToAES<T>(T obj)
        {
            //Key
            byte[] keyArr = new byte[] { 0x540x480x450x200x4B0x490x4E0x470x200x4D0x490x4E0x530x450x4F0x4b };
 
            //Convert obj to byte array
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            MemoryStream memoryStream = new MemoryStream();
            binaryFormatter.Serialize(memoryStream, obj);
            var plainArr = memoryStream.ToArray();
            memoryStream.Close();
 
            //Initialization Vector (IV 생성)
            byte[] iV = Encoding.UTF8.GetBytes("THEJOEUNCOMPUTER");
 
            //Encryption
            Aes aes = Aes.Create();
            aes.KeySize = 128;
            aes.Key = keyArr;
            aes.Padding = PaddingMode.PKCS7; //padding 방법
            aes.IV = iV; //대칭 Vector = default Vector
            ICryptoTransform aesForm = aes.CreateEncryptor(aes.Key, aes.IV); //암호화 기본 작업 인터페이스 변수에 Key, Iv를 가진 암호화 개체 생성
            MemoryStream enMemoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(enMemoryStream, aesForm, CryptoStreamMode.Write);
            StreamWriter streamWriter = new StreamWriter(cryptoStream);
            streamWriter.Write(plainArr);
            byte[] chiperArr = enMemoryStream.ToArray();
            enMemoryStream.Close();
 
            return chiperArr;
        }
 
        //AES-128 Decryption
        public static T DecryptionByte<T>(byte[] chiperArr)
        {
            //Key
            byte[] keyArr = new byte[] { 0x540x480x450x200x4B0x490x4E0x470x200x4D0x490x4E0x530x450x4F0x4b };
 
            ////Convert obj to byte array
            //BinaryFormatter binaryFormatter = new BinaryFormatter();
            //MemoryStream memoryStream = new MemoryStream();
            //binaryFormatter.Serialize(memoryStream, obj);
            //var plainArr = memoryStream.ToArray();
            //memoryStream.Close();
 
            //Initialization Vector (IV 생성)
            byte[] iV = Encoding.UTF8.GetBytes("THEJOEUNCOMPUTER");
 
            //Decryption
            Aes aes = Aes.Create();
            aes.KeySize = 128;
            aes.Key = keyArr;
            aes.Padding = PaddingMode.PKCS7; //padding 방법
            aes.IV = iV; //대칭 Vector = default Vector
 
            ICryptoTransform dcryp = aes.CreateDecryptor(aes.Key, aes.IV);
            MemoryStream ms = new MemoryStream();
            CryptoStream decrypStream = new CryptoStream(ms, dcryp, CryptoStreamMode.Write);
            decrypStream.Write(chiperArr, 0, chiperArr.Length);
            decrypStream.FlushFinalBlock();
 
            ms.Position = 0;
            byte[] temp = new byte[ms.Length];
            ms.Read(temp, 0, temp.Length);
            ms.Close();
 
            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream ms2 = new MemoryStream(temp, 0, temp.Length);
            formatter.Deserialize(ms2);
 
            return (T)temp;
            
 
            //ICryptoTransform cryptoTransform = aes.CreateDecryptor(aes.Key, aes.IV); //암호화 기본 작업 인터페이스 변수에 Key, Iv를 가진 복호화 개체 생성
            //MemoryStream memoryStream = new MemoryStream(chiperArr);
            //CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read);
            //StreamReader streamReader = new StreamReader(cryptoStream);
            //MemoryStream memory2 = new MemoryStream();
            //memory2.Write()
            //var ICustomFormatter = new BinaryFormatter();
            //ICustomFormatter.Deserialize(streamReader);
            //var plainObject = streamReader.ReadToEnd();
 
            //ICryptoTransform descrypt = aes.CreateDecryptor(aes.Key, aes.IV);
            //MemoryStream ms1 = new MemoryStream(chiperArr);
            //CryptoStream cryptoStream = new CryptoStream(ms1, descrypt, CryptoStreamMode.Read);
            //byte[] temp = new byte[chiperArr.Length];
            //cryptoStream.Write(temp, 0, temp.Length);
            //StreamReader ms1Reader = new StreamReader(cryptoStream);
            //ms1Reader.
            //StreamWriter ms1Writer = new StreamWriter(cryptoStream);
            //ms1Writer.Write(chiperArr);
 
            //ms1.Read(temp, 0, temp.Length);
            //MemoryStream ms2 = new MemoryStream(temp);
            //ms2.Write(temp, 0, temp.Length);
 
            //IFormatter formatter = new BinaryFormatter();
            //ms2.Seek(0, SeekOrigin.Begin);
            //T obj = (T)formatter.Deserialize(ms1);
 
            //return obj;
        }
    }
}
 
cs





'C# > Problems' 카테고리의 다른 글

멀티스레딩 + SetCursorPosition에서 생긴 문제 [해결]  (0) 2019.04.01
하는중  (0) 2019.04.01
공부할 것과 정리중인 것  (0) 2019.03.28
공부중  (0) 2019.03.27
Console.Read() 의 형변환 [해결]  (0) 2019.03.25
:

멀티스레딩 + SetCursorPosition에서 생긴 문제 [해결]

C#/Problems 2019. 4. 1. 17:37

구상은 (x,y)좌표를 기반으로 (0,0)에서는 출력하는 스레드가 활동을 하고,

(0,20)에서는 입력받는 스레드가 활동을 하는 것을 구상했다.


(0,0)에서 메뉴를 출력한 후에 (0,20)에서 입력받고 다시 (0,0)으로 올라가서 그에 대한 답을 출력하는 방식으로 코딩을 했는데

자꾸 위의 사진처럼 (0,0)이 끝난 뒤에 (0,20)으로 내려가지 않고 저 자리에서 입력을 1회 해야했다.

이처럼 aaaaa의 좌표에서 1회 입력을 해야만 ddddd가 있는 (0,20)좌표로 커서가 이동했다.

무엇이 문제일까 계속 만져보고 SetCursorPosition을 따로 메서드에 지정하여 lock도 걸어보았지만 똑같았다.

또, 이렇게 멋대로 커서가 왔다갔다하면서 출력이 늘어질 때도 있었다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
        public void SetCursor(int x, int y) //커서 좌표 지정 lock하여 한번에 1스레드만 이용가능
        {
            lock(lockObject)
            {
                Console.SetCursorPosition(x, y);
            }
        }
        public void StartOutputThread() //아웃풋 스레드 생성 및 실행
        {
            this.SetCursor(00);
            ThreadStart outputThreadStart = new ThreadStart(this.MenuOutput);
            Thread outputThread = new Thread(outputThreadStart);
            outputThread.Start();
        }
        public void StartInputThread() //인풋 스레드 생성 및 실행
        {
            this.SetCursor(020);
            ThreadStart inputThreadStart = new ThreadStart(this.Input);
            Thread inputThread = new Thread(inputThreadStart);
            inputThread.Start();
        }
cs

(스레드와 직접적으로 관련된 메서드 부분)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void SetCursor(int x, int y) //커서 좌표 지정 lock하여 한번에 1스레드만 이용가능
        {
            lock(lockObject)
            {
                Console.SetCursorPosition(x, y);
            }
        }
        public void StartOutputThread() //아웃풋 스레드 생성 및 실행
        {
            this.SetCursor(00);
            ThreadStart outputThreadStart = new ThreadStart(this.MenuOutput);
            Thread outputThread = new Thread(outputThreadStart);
            outputThread.Priority = ThreadPriority.Highest;
            outputThread.Start();
        }
        public void StartInputThread() //인풋 스레드 생성 및 실행
        {
            this.SetCursor(020);
            ThreadStart inputThreadStart = new ThreadStart(this.Input);
            Thread inputThread = new Thread(inputThreadStart);
            inputThread.Priority = ThreadPriority.Lowest;
            inputThread.Start();
        }
 
cs

아웃풋 스레드와 인풋 스레드 간의 우선순위때문에 그러는 것 같아서

아웃풋 스레드에게 최우선순위를 주고, 인풋 스레드에게 최하 우선순위를 주었지만, 똑같은 현상이 반복되었다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        public void SetCursor(int x, int y) //커서 좌표 지정 lock하여 한번에 1스레드만 이용가능
        {
            lock(lockObject)
            {
                Console.SetCursorPosition(x, y);
            }
        }
        public void StartOutputThread() //아웃풋 스레드 생성 및 실행
        {
            this.SetCursor(00);
            ThreadStart outputThreadStart = new ThreadStart(this.MenuOutput);
            Thread outputThread = new Thread(outputThreadStart);
            outputThread.Start();
            this.StartInputThread();
        }
        public void StartInputThread() //인풋 스레드 생성 및 실행
        {
            this.SetCursor(020);
            ThreadStart inputThreadStart = new ThreadStart(this.Input);
            Thread inputThread = new Thread(inputThreadStart);
            inputThread.Start();
        }
 
cs
호출을 연쇄적으로 하게끔 아웃풋스레드 메서드에서 인풋스레드 메서드를 호출해봤으나 똑같았다.

키포인트는 제어권인거 같은데 풀 수가 없었다.

그렇게 이것저것 해보고 조언도 구해서 결국 답을 찾았다.

제어권 문제가 정답이었고, 그의 해답은 async, await에 있었다.

해결을 위해 async, await을 공부하는 중에 "그렇다면 스레드가 활동 중일 때 안 놓으면 되지않나?" 싶어서 Thread.Join();을 사용해봤다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
        public void SetCursor(int x, int y) //커서 좌표 지정 lock하여 한번에 1스레드만 이용가능
        {
            lock(lockObject)
            {
                Console.SetCursorPosition(x, y);
            }
        }
        public async void StartOutputThread() //아웃풋 스레드 생성 및 실행
        {
            this.SetCursor(00);
            ThreadStart outputThreadStart = new ThreadStart(this.MenuOutput);
            Thread outputThread = new Thread(outputThreadStart);
            outputThread.Start();
            outputThread.Join();
        }
        public async void StartInputThread() //인풋 스레드 생성 및 실행
        {
            this.SetCursor(020);
            ThreadStart inputThreadStart = new ThreadStart(this.Input);
            Thread inputThread = new Thread(inputThreadStart);
            inputThread.Start();
            inputThread.Join();
        }
cs

바로 outputThread.Join(); inputThread.Join(); 부분이다.

Thread의 Join 메서드는 사용한 스레드의 작업이 완료될때까지 호출자를 차단한다.

즉 App.cs에서 StartOuputThread() 메서드를 호출했는데, 원래는 outputThread.Start();가 실행되고 작업이 완료되기 전에 App.cs로 돌아가 StartInputThread(); 메서드를 호출하여 인풋스레드를 실행하는 것이다.   

하지만 위처럼 아웃풋 스레드를 실행하고, Join메서드를 사용해주면 작업이 완료되기 전에 호출자가 제어권을 가져갈 수 없다.

그렇게 해결을 했다.



이제 이 코드에 async, await, task를 사용해서 구현해봐야겠다.




-async await 공부중... 공부하고 코드 적용 후 업데이트 할 예정-

'C# > Problems' 카테고리의 다른 글

암호화하여 직렬화, 복호화하여 역직렬화 [문제해결중]  (0) 2019.04.10
하는중  (0) 2019.04.01
공부할 것과 정리중인 것  (0) 2019.03.28
공부중  (0) 2019.03.27
Console.Read() 의 형변환 [해결]  (0) 2019.03.25
:

하는중

C#/Problems 2019. 4. 1. 03:10

PlayerInventory.zip


:

공부할 것과 정리중인 것

C#/Problems 2019. 3. 28. 17:56

IEnumerator
IEnumerable

object 형

Collection

ArrayList
Predicate
delegate


delegate 기능 
함수들을 통합 실행할 수 있음
delegate에 메서드를 참조하게 하여,
같은 타입의 인자를 보낼 때, 가지고 있는 메서드를 대신 호출
그래서 delegate type을 받는 메서드는 전달받은
delegate를 가지고 다른 메서드를 호출하여 그 값을 이용할 수 있다.

delegate chain
메서드를 delegate에 집어넣고 이름을 이용해 호출가능
(여러가지 메서드를 집어넣고 쓸 수 있다.
메서드의 주소를 집어넣고 delegate가 호출하는 식)
즉, delegate는 Method를 가리킬 수 있는 Type이다.

Call-Back Method
A의 메서드를 호출할 때, B메서드를 매개변수로 보내준다.
그리고 A메서드가 B메서드를 호출하는 것이 Call-Back Method

Event
인스턴스의 변화가 생길때 해당되는 값을 실행
던지는 객체, 받는 객체, 핸들러로 구성
if를 이용해 조건을 달고 조건이 해당하면 event변수에 있는
delegate주소로 가서 delegate를 호출하는 형식.
즉 event 발생시 event변수에 있는 delegate를 호출
호출된 delegate는 갖고 있는 Method를 호출

:

공부중

C#/Problems 2019. 3. 27. 22:13

Starcraft

1. 종족 선택(Class)
2. 건물 및 일꾼 4기 생성 (Class Field)
3. 명령어 유닛선택 시 유닛의 목록 출력 (Class Field output)
4. 이동, 공격, 멈춤 기능 (Method)
5. 기본적으로 일을 하는 중이어서 시간단위로 자원 증가
6. 프로토스는 Shield HP따로, Shield는 시간단위 회복
7. 테란은 Land 기능, if Land state시 일꾼 일 정지
8. 저그는 라바 3기 드론 4기
9. 라바는 드론으로 변경가능하게



Class 종족
ㄴ field 유닛, 건물


유닛, 건물 인스턴스 생성시
그의 주소를 인스턴스 변수 배열에 하나씩 집어넣는다.
배열이 NULL일 경우 그 칸에 인스턴스의 주소를 넣는다.
출력시 배열을 반복하여 출력하면 된다.
배열에서 파괴되면 Index를 주어서 파괴하면 된다.



IEnumerator
object Current { get; }
bool MoveNext();
void Reset();


그룹을 만들고 싶거나 오브젝트를 만들 때, 두 개의 방법이 있음
오브젝트의 Array를 만들거나 오브젝트의 Collection을 만들거나
배열은 만들고 사용하는데 유용하고 개체수가 정해진 오브젝트를 관리하는데 유용

컬렉션은 개체를 관리하는데 있어 유연한 방법을 제공한다
Array와는 다르게 컬렉션은 동적으로 확장 및 축소가 가능(List 같은)


Generic List vs ArrayList


Get&Set
Predicate ? (델리게이트 등장!)

delegate = 대리자로서 모든 메서드에 연결할 수 있다.
즉, A메서드의 매개변수로 메서드를 전달 할 수 있다.

아직 설명은 못하겠는데 delegate랑 ienumerable, ienumerator는 사기다

:

Console.Read() 의 형변환 [해결]

C#/Problems 2019. 3. 25. 20:31

Console.Read() 메서드는 기본적으로 integer 형을 반환하게 되어있는데,

'4'를 입력하고 integer 형의 변수로 값을 받았을 때, 52가 출력된다.



이는 Convert.Tochar를 이용하고, 파싱을 다시 해야하는데

이는 공부해보고 Read는 integer형으로 받았는데 왜 다른 값이 나오는지 알아봐야겠다.

이번 주 안에 풀어서 해답과 함께 포스팅해야지






-해답

Console.Read() 메서드는 integer형을 반환하나, 전달받은 값을 문자로 받고, ASCII Code로 변환하여 반환한다.

결국 integer형을 반환하는 것은 같지만, 그래서 내가 넣은 값이 그대로 return되지 않았다.

: