C# NAudio MicroPhone 볼륨 조절

프로그래밍 언어/C# 2020. 8. 20. 21:07

private void sourceStream_DataAvailable(object sender, NAudio.Wave.WaveInEventArgs e)

{

    byte[] encoded = e.Buffer;

    if (reLen + encoded.Length < 70000)

    {

        if (recordingFirstSkip > 6)

        {

            encoded.CopyTo(recordingStream, reLen);

            int i;

           float multiplier = 12.0f; // 볼륨 Gain

           for (i = 0; i < encoded.Length; i = i + 2)

           {

               Int16 sample = BitConverter.ToInt16(encoded, i);

               sample = (Int16)(sample * multiplier);

               byte[] sampleBytes = BitConverter.GetBytes(sample);

               encoded[i] = sampleBytes[0];

               encoded[i + 1] = sampleBytes[1];

            }

            encoded.CopyTo(recordingStream2, reLen);

            reLen += encoded.Length;

           }

          else

         {

              encoded.CopyTo(recordingStream, reLen);

              encoded.CopyTo(recordingStream2, reLen);

              recordingFirstSkip++;

         }

    }

}

 

 

 

 

'프로그래밍 언어 > C#' 카테고리의 다른 글

C# RGB 출력, YUV420 -> RGB로 출력  (0) 2020.09.01
C# 이미지 그리기, 출력  (0) 2020.08.21

설정

트랙백

댓글

Visual Studio 2019 한글 형식(인코딩). 유니코드, EUC-KR

프로그래밍 언어/WinApi 2020. 7. 28. 10:17

문자를 입력 받았을 경우, 한글인지 아닌지 판별하기 위하여 작업 도중,

 

WCHAR, char의 한글 형식을 같은 유니코드를 사용하고 있는 줄 알았으나

 

값이 다르게 나와서 찾아 보았다.

 

 

한글의 형식은 컴파일러마다, 운영체제마다 다르다고 한다.

 

Window10, Visual Studio 2019의 환경에서

 

WCHAR 형은 유니코드를 사용하고

 

char 형은 EUC-KR을 사용하는 것 같다.

 

ex)

    //WCHAR eee[20] = TEXT("가나하");
    unsigned char eee[20] = "가나하";
    unsigned char eee1;
    unsigned char eee2;

    eee1 = *((unsigned char*)eee + 0); 
    eee2 = *(((unsigned char*)eee) + 1); 
    TextMB::Box(eee1, eee2);

    eee1 = *((unsigned char*)eee + 2);
    eee2 = *(((unsigned char*)eee) + 3);
    TextMB::Box(eee1, eee2);

    eee1 = *((unsigned char*)eee + 4);
    eee2 = *(((unsigned char*)eee) + 5);
    TextMB::Box(eee1, eee2);

 

  유니코드 WCHAR char
AC00 00AC B0A1
B098 98B0 B3AA
D558 58D5 C7CF

 

둘 다, 두번째 바이트에 최상위 비트가 1인지 0인지 확인하면 한글 판별이 가능할 것 같다.

 

그런데 WCHAR의 값은 리틀엔디안 형식이니 반대로 나온게 맞는것 같은데,

char의 값은 그대로 나왔다. 뭐지..?

 

-- 유니코드 문자표

https://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_%EC%98%81%EC%97%AD

https://ko.wikipedia.org/wiki/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C_A000~AFFF

 

-- EUC-KR 문자표

https://uic.win/ko/charset/show/euc-kr/

 

-- CP949

https://charset.fandom.com/ko/wiki/CP949

 

 

EUC-KR를 찾다가 보니 CP949, KS X 1001, KS X 1003 등등 여러 인코딩이 나오던데

언급은 하지 않겠다...

https://codingdog.tistory.com/entry/cp949-vs-euc-kr-%EC%96%B4%EB%96%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90%EC%9D%B4-%EC%9E%88%EB%8A%94%EC%A7%80-%EA%B0%84%EB%8B%A8%ED%9E%88-%EC%95%8C%EC%95%84%EB%B4%85%EC%8B%9C%EB%8B%A4

설정

트랙백

댓글

win32api 서브클래싱, 전역클래싱, 슈퍼클래싱

프로그래밍 언어/WinApi 2020. 7. 27. 13:23

Tab(탭) 키로 각 차일드 윈도우간 포커스 이동을 하려고 했더니 클래싱을 사용해야할 것 같다.

 

# 서브클래싱

서브클래싱이란 도스의 인터럽트 가로채기와 개념적으로 동일하며 윈도우 프로시저로 전달되는 메시지를 중간에
가로채는 기법이다.

운영체제 -> 서브클래스 프로시저 -> 윈도우 프로시저

서브클래스 프로시저는 메시지를 먼저 받아서 다음의 세가지 방법으로 이 메시지를 처리할 수 있다.
① 통과 : 관심 없는 메시지는 바로 윈도우 프로시저로 넘겨버린다.
② 직접 처리 : 원하는 메시지가 왔을때 중간에 메시지를 처리하고 리턴. 윈도우 프로시저로는 전달되지않는다.
③ 변형 : 메시지를 받아서  원하는 변경 후 윈도우 프로시저로 보낸다. (키입력의 변경등)


새로운 윈도우 프로시저를 생성해서 아래 함수를 통해 변경할 대상 윈도우의 새로운 메시지 처리 함수를 지정한다.
원래번지=SetWindowLongPtr(변경할 대상윈도우,GWLP_WNDPROC,서브클래스 프로시저)서브 클래스 프로시저에서는 원하는 메시지 이외에는 다시 윈도우 프로시저로 넘겨줘야 하기때문에 관심없는
메시지에 대해서는 프로시저 마지막에 아래 함수를 사용하여 메시지를 다시 윈도우 프로시저로 넘겨주면된다.
LRESULT CallWindowProc(WNDPRCO lpPrevWndFunc,HWND hWnd,UINT Msg,WPARAM wParam,
LPARAM lParam);
메시지를 마음대로 변경할 수 있는 서브클래싱은 아주 유용하고도 강력한 기법임에 틀림없지만 그 이면에는 항상
잠재적인 위험성이 도사리고 있어 아주 조심스럽게 사용해야 한다. 꼭 필요하지 않는 한 서브클래싱은 하지 않는
것이 좋지만 불가피할 경우는 다음의 주의사항을 잘 숙지하고 안전하게 사용하자.

1. 윈도우의 원래 기능을 보존할 것.
2. 필요한 메시지를 제외한 메시지는 온전하게 윈도우 프로시저로 보낼 것.
3. 여분 메모리(cbWndExtra,cbClsExtra)를 절대로 건드리지 말것.
4. 여분 메모리가 필요한 경우 윈도우 프로퍼티를 사용할 것.

 

 

예제)

 

HWND hSub;        // 서브클래싱할 윈도우 핸들
WNDPROC wp_OldSubProc;        // 서브클래싱하기 전의 윈도우 프로시져 주소

 

 

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam) 
{ 
    ... 
    WNDCLASS WndClass;


    switch (iMessage)

    { 
    case WM_CREATE: 

 

    ...

 

        // 프로시저 변경

        wp_OldSubProc = (WNDPROC)SetWindowLong( hSub, GWL_WNDPROC, (LONG)Test1Proc );

 

    ...

 

        // 프로그램 종료시 다시 원래의 프로시져 주소로 교체 해준다.
        SetWindowLong( hSub, GWL_WNDPROC, (LONG)wp_OldSubProc );

    ...

}

 

 

LRESULT CALLBACK Test1Proc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
    switch( iMessage )
    {
    case WM_KEYDOWN:
        break;
    }

    return CallWindowProc( wp_OldSubProc, hWnd, iMessage, wParam, lParam);
}




# 전역 서브클래싱

서브 클래싱도 시점과 방법, 그리고 효과가 미치는 범위에 따라 다음 두 가지로 분류된다.

■ 인스턴스 서브클래싱 : 특정한 하나의 윈도우 만을 대상으로 서브클래싱, SetWindowLongPtr 사용된다.

■ 전역 서브클래싱 : 윈도우 클래스에 대해 서브 클래싱, 이미 만들어진 윈도우에 대해서는 효과가 없으며 앞으로
  만들어질 윈도우만 영향을 받는다. SetClassLongPtr이 사용된다.


에디트를 생성하고 에디트를 대상으로 전역 서브 클래싱을 할 경우 에디트가 속한 "edit"윈도우 클래스가
서브 클래싱의 대상
이 되므로 서브 클래싱한 이 후 생겨나는 모든 edit는 서브 클래싱의 영향을 받게된다.

SetClassLongPtr(hEdit1,GCLP_WNDPROC,(LONG_PTR)OldEditProc);전역 클래싱은 윈도우 클래스 자체를 바꾸는 것이지만 다른 프로세스에는 영향을 주지 못한다.
시스템 전역 클래스에 정보는 시스템이 가지고 있지만 각 프로세스가 참조하는 클래스 정보는 응용프로그램이
시작될 때 시스템으로 전달받는 복사본일 뿐이다. 즉 서브클래싱은 같은 프로세스 내에서만 효력을 발휘한다.


# 슈퍼클래싱

슈퍼클래싱은 기존클래스(=베이스 클래스)의 정보를 바탕으로 하여 완전히 새로운 클래스를 만드는 것이다.
슈퍼클래싱에 의해 새로 만들어진 윈도우 클래스는 베이스 클래스와 동일하지만 여기에 변화를 주면 원하는대로
윈도우 클래스를 수정할 수 있다.

슈퍼클래싱의 핵심 함수는 GetClassInfo(Ex)함수이다.

BOOL GetClassInfo(HINSTANCE hInstance,LPCTSTR lpClassName,LPWNDCLASS lpWndClass);이 함수는 lpClassName 윈도우 클래스의 정보를 조사하여 lpWndClass가 가리키는 WNDCLASS 구조체에
채운다. 첫번 째 인수는 이 윈도우 클래스를 만든 응용프로그램의 인스턴스 핸들이되 버튼, 에디트 등의 시스템에
의해 만들어진 윈도우 클래스일 경우는 NULL을 주면 된다. 이 함수 호출에 의해 윈도우 클래스의 정보를 조사할
수 있는데 예를 들자면 GetClassInfo(NULL,"edit",&WndClass); 함수를 호출하면 "edit" 윈도우 클래스의 정보를
WndClass 구조체에 복사한다. 이 함수는 등록된 윈도우 클래스의 정보를 다시 돌려받으므로 RegisterClass함수의
반대 함수라고 생각하면 쉽다.

WndClass 구조체에 윈도우 클래스의 정보가 조사되었으므로 이 구조체의 정보를 바탕으로 적절히 수정한 후 다시
RegisterClass로 새로운 윈도우 클래스를 등록하는 것이 바로 슈퍼클래싱이다.

원본(GetClassInfo) ->  사본(수정) -> 새로등록(RegisterClass)

WndClass 구조체의 정보중 몇가지는 반드시 수정되어야 한다. 일단 클래스 이름이 베이스 클래스와 같아서는
안되므로 lpszClassName 멤버가 달라져야 한다. 또한 hInstance 멤버에는 이 윈도우 클래스를 등록하는 응용
프로그램의 인스턴스 핸들을 대입해야 하는데 그래야 이 인스턴스가 종료될 때 등록해제 된다. 그리고 가장 중요한
lpfnWndProc멤버를 수정하여 응용 프로그램이 정의한 윈도우 프로시저로 메시지를 보내도록 해야 할 것이다.
단 이때 기존의 윈도우 프로시저 번지는 복구를 위해 잘 보관해 두어야 한다.


[슈퍼 클래싱 예제]
LRESULT CALLBACK SuperProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    switch (iMessage)
    {
    ...
    }
    return CallWindowProc(OldEditProc,hWnd,iMessage,wParam,lParam);
}

LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
    ...
    WNDCLASS WndClass;


    switch (iMessage)

    {
    case WM_CREATE:
        GetClassInfo(NULL,TEXT("edit"),&WndClass); // "edit"클래스에 대한 정보 조사
        WndClass.hInstance=g_hInst;
        WndClass.lpszClassName=TEXT("SuperEdit"); // 새로운 이름 등록
        WndClass.hCursor=LoadCursor(NULL,IDC_WAIT); // 커서 변경
        OldEditProc=WndClass.lpfnWndProc; // 기존의 윈도우 프로시저 저장
        WndClass.lpfnWndProc=SuperProc; // 새로운 프로시저로 변경
        RegisterClass(&WndClass); // 수정한 윈도우 등록
        hEdit1=CreateWindow(TEXT("SuperEdit"),NULL,WS_CHILD | WS_VISIBLE |
            WS_BORDER | ES_AUTOHSCROLL,
            10,10,200,25,hWnd,(HMENU)ID_EDIT1,g_hInst,NULL);
        SetFocus(hEdit1);
        return 0;

    ...
}

 

서브 클래싱과 슈퍼클래싱은 둘다 사용목적이 비슷하며 상호 대체성이 있다. 어떤 방법을 쓸 것인가는 상황에
따라 다르겠지만 대체로 슈퍼클래싱이 더 안전하고 부릴 수 있는 기교도 더 많다.
특정 윈도우 하나만 수정할 때는 인스턴스 서브클래싱을 사용하고 다량의 윈도우를 한꺼번에 바꿀 때는 전역 또는
슈퍼클래싱을 사용하는 것이 편리하다.

 

 

 

 

참고 사이트 : http://egloos.zum.com/itbaby/v/4513218

참고 사이트 : http://blog.daum.net/creazier/15309359

설정

트랙백

댓글

Visual Studio 2019 win32api 아이콘 변경이 안된다

프로그래밍 언어/WinApi 2020. 7. 22. 13:32

리소스에 아이콘 추가 후,

 

메인 클래스에

 

wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_ICON1));

 

를 수정해도 탐색기에 표시되는 아이콘이 변경되지 않았다.

 

 

자료를 찾아도 MFC, C#은 나와있지만 win32api는 없었다.

아마 내부적으로 캐시된게 잘 처리가 안되지 않았을까... 라고 누가 그러더라..

아래와 같이 다시 불러와 주니 바뀌었다.

 

 

프로젝트에서 기존항목을 누르고 변경할 아이콘을 선택한 후에 컴파일을 하니 바뀌었다.

 

다시 해보니 안된다....

 

껐다 키고 뭔짓을 해야된다.....

설정

트랙백

댓글

Visual Studio 2019 sprintf 에러 끄기

프로그래밍 언어/WinApi 2020. 7. 22. 12:05

Visual Studio 2019에서 컴파일시, sprintf 를 사용할 수 없음으로 에러가 뜰 경우

 

심각도 코드 설명 프로젝트 파일 줄 비표시 오류(Suppression) 상태
오류 C4996 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. MP_works C:\Users\root\Documents\Visual Studio 2019\Projects\MP_works\MP_works\MP_works.cpp

 

 

 

 

아래와 같이 대처

---> 메뉴에 프로젝트 -> 속성 -> 왼쪽 메뉴에 구성속성 -> C/C++ -> 일반 -> SDL검사를 아니오로 변경

 

 

 

설정

트랙백

댓글

USBISP-MK2 Manual

Embedded/펌웨어? 2020. 6. 16. 11:30

--- 모드별 핀사양

 

 

 

 

--- USBISP MK2 Supported Devices

 

<ISP Mode>

ATmega1280 ATmega1281 ATmega1284P ATmega1284 ATmega128A ATmega128RFA1 ATmega128 ATmega162 ATmega164A ATmega164PA ATmega164P ATmega165A ATmega165PA ATmega165P ATmega168A ATmega168PA ATmega168P ATmega168 ATmega169A ATmega169PA ATmega169P ATmega16A ATmega16HVBrevB ATmega16HVB ATmega16M1 ATmega16U2 ATmega16U4 ATmega16 ATmega2560 ATmega2561 ATmega324A ATmega324PA ATmega324P ATmega3250A ATmega3250P ATmega3250 ATmega325A ATmega325P ATmega325 ATmega328P ATmega328 ATmega3290P ATmega3290 ATmega329A ATmega329PA ATmega329P ATmega329 ATmega32A ATmega32C1 ATmega32HVBrevB ATmega32HVB ATmega32M1 ATmega32U2 ATmega32U4 ATmega32 ATmega48A ATmega48PA ATmega48P ATmega48 ATmega640 ATmega644A ATmega644PA ATmega644P ATmega644 ATmega6450A ATmega6450P ATmega6450 ATmega645A ATmega645P ATmega645 ATmega6490A ATmega6490P ATmega6490 ATmega649A ATmega649P ATmega649 ATmega64A ATmega64C1 ATmega64M1 ATmega64 ATmega8515 ATmega8535 ATmega88A ATmega88PA ATmega88P ATmega88 ATmega8A ATmega8U2 ATmega8 ATtiny13A ATtiny13 ATtiny1634 ATtiny167 ATtiny2313A ATtiny2313 ATtiny24A ATtiny24 ATtiny25 ATtiny261A ATtiny261 ATtiny26 ATtiny4313 ATtiny43U ATtiny44A ATtiny44 ATtiny45 ATtiny461A ATtiny461 ATtiny48 ATtiny828 ATtiny84A ATtiny84 ATtiny85 ATtiny861A ATtiny87 ATtiny88 AT90CAN128 AT90CAN32 AT90CAN64 AT90PWM161 AT90PWM1 AT90PWM216 AT90PWM2B AT90PWM316 AT90PWM3B AT90PWM81 AT90USB1286 AT90USB1287 AT90USB162 AT90USB646 AT90USB647 AT90USB82 ATA6285 ATA6286

 

<PDI Mode>

ATxmega128A1U ATxmega128A1 ATxmega128A3U ATxmega128A3 ATxmega128A4U ATxmega128B1 ATxmega128B3 ATxmega128C3 ATxmega128D3 ATxmega128D4 ATxmega16A4U ATxmega16A4 ATxmega16C4 ATxmega16D4 ATxmega192A3U ATxmega192A3 ATxmega192C3 ATxmega192D3 ATxmega256A3BU ATxmega256A3B ATxmega256A3U ATxmega256A3 ATxmega256C3 ATxmega256D3 ATxmega32A4U ATxmega32A4 ATxmega32C4 ATxmega32D4 ATxmega384C3 ATxmega384D3 ATxmega64A1U ATxmega64A1 ATxmega64A3U ATxmega64A3 ATxmega64A4U ATxmega64B1 ATxmega64B3 ATxmega64C3 ATxmega64D3 ATxmegaD4

 

<TPI Mode>

ATtiny4 ATtiny5 ATtiny9 ATtiny10 ATtiny20 ATtiny40

 

USBISP_MK2_manual.pdf
0.64MB

'Embedded > 펌웨어?' 카테고리의 다른 글

ST-link v2 readout protection (RDP) 설정  (0) 2022.12.05
C 예제) AES-128 ECB  (1) 2019.06.10
stm32f05xx CRC  (0) 2019.04.16

설정

트랙백

댓글

Blocking / Non-Blocking

통신 2019. 9. 18. 20:23

Blocking

I/O 작업은 유저레벨에서 직접 수행할 수 없다. 실제 I/O를 수행하는것은 커널레벨에서만 가능하다. 따라서 유저 프로세스(또는 쓰레드)는 커널에게 I/O를 요청해야한다. I/O에서 블로킹 형태의 작업은 유저 프로세스가 커널에게 I/O를 요청하는 함수를 호출하고, 커널이 작업을 완료되면 함수가 작업 결과를 반환한다.

 

http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch06lev1sec2.html

I/O 작업이 진행되는동안 유저 프로세스는 자신의 작업을 중단한채 대기해야한다. I/O작업이 CPU자원을 거의 쓰지 않기 때문에 이런 형태의 I/O는 리소스 낭비가 심하다.

만약 여러 클라이언트가 접속하는 서버를 블로킹방식으로 구현한다고 가정해보자. I/O작업이 blocking 방식으로 구현되면 하나의 클라이언트가 I/O작업을 진행하면 해당 프로세스(또는 쓰레드)가 진행하는 작업을 중지하게 된다. 따라서 다른 클라이언트의 작업에 영향을 미치지 않게 하기 위해서 클라이언트 별로 별도의 쓰레드를 만들어 연결시켜주어야 할 것이다. 그러면 쓰레드 수는 접속자 수가 많아질 수록 엄청나게 많아지게 된다. 쓰레드가 많으면 CPU의 컨텍스트 스위칭 횟수가 증가할 것이며, 이때 사용되는 컨텍스트 스위칭 비용 때문에, 실제 작업하는 양에 비하여 훨씬 비효율적으로 동작하게 될 것이다.

 

Non-Blocking

Blocking 방식의 비효율성을 극복하고자 만들어진 것이 Non-Blocking 방식이다. Non-Blocking은 I/O작업을 진행하는 동안 유저 프로세스의 작업을 중단시키지 않는다. 유저 프로세스가 커널에게 I/O를 요청하는 함수를 호출하면, 함수는 I/O를 요청한 다음 진행상황과 상관없이 바로 결과를 반환한다.

 

http://www.masterraghu.com/subjects/np/introduction/unix_network_programming_v1.3/ch06lev1sec2.html

 

위 그림은 Non-Blocking 방식으로 구현된 I/O의 대표적인 사례를 잘 보여준다. 유저 프로세스는 recvfrom함수를 호출하여 커널에게 해당 소켓으로부터 데이터를 받아오고 싶다고 요청하고 있다. 커널은 이 요청에 대해서 상대방의 데이터를 전송 받아서 recvBuffer에 저장하고, 유저에게 그 내용을 복사해줘야 한다. 상대방으로 부터 데이터를 받는 중에 recvBuffer가 비어있다면 유저 프로세스가 커널에게 받아올 수 있는 정보는 없다. 따라서 recvfrom 함수는 아직 작업 진행중이란 의미로 "EWOULDBLOCK"을 리턴한다. 이 결과를 받은 유저 프로세스는 다른 작업을 진행할 수 있다. 만약 recvBuffer에 유저가 받을 수 있는 데이터가 있다면, 버퍼로 부터 데이터를 복사하여 받아온다. recvBuffer는 커널이 가지고 있는 메모리에 적재되어 있으므로 메모리간 복사가 일어나 I/O보다 훨씬 빠른 속도로 데이터를 받아올 수 있다. 이때 recvfrom함수는 빠른 속도로 읽을 수 있는 데이터를 복사해주고 복사한 데이터의 길이와 함께 반환한다. 위의 모든 반환이 I/O의 진행시간과는 관계없이 빠르게 동작하기 때문에, 유저 프로세스는 자신의 작업을 오랜시간 중지하지 않고도 I/O 처리를 수행할 수 있다.

 

Socket에서 Non-Blocking 구현

socket 프로그래밍에서 해당 소켓의 I/O Blocking/Non-Blocking 모드를 결정할 수 있다.

 

//ioctlsocket함수: 소켓의 I/O 상태를 변경하는 함수 //리눅스에서는 ioctl함수가 같은 기능을 지원한다. ULONG isNonBlocking = 1; ioctlsocket(socket, //Non-Blocking으로 변경할 소켓 FIONBIO, //변경할 소켓의 입출력 모드 &isNonBlocking //넘기는 인자, 여기서는 nonblocking설정 값 );

 

두 번째 인자에 어떤 값을 넣느야에 따라서 설정 값의 의미가 달라지긴 하지만, Non-Blocking으로 만드는데에는 이 호출만으로 충분하다. 소켓은 초기 설정이 Blocking으로 되어있으므로 Non-Blocking 모드로 진행하기 위해서는 이 함수 호출이 필수적이다.

 

char str[BUF_SIZE] = {0,}; //받을 버퍼 unsigned int strLen = 0; //받고싶은 데이터의 길이 unsigned int length = 0; //지금까지 받은 데이터의 길이 unsigned int recvLen = 0; //이번에 받은 데이터의 길이 ... while(TRUE){ if ( recvLen = recv( sock, str+length, strLen, 0) < 0 ){ //recvfrom 호출하여 결과값을 받는다. 0보다 작으면 받을 수 있는 데이터가 없는것 if ( WSAGetLastError() == WSAEWOULDBLOCK ){ //WOULDBLOCK이라면 대기시킨다. Sleep( 2000 ); /* Sleep for 2 milliseconds */ } else{ printf("No data Error.\n"); break; } } else { length += recvLen; if(length >= strLen) //다받았으면 중지 break; } }

 

while문을 사용하여 Blocking 모델과 다를바 없이 사용하고 있기 때문에 좋은 사용 방법이라고는 생각하지 않지만, 각 부분을 따로 놓고 생각하면 Non-Blocking형식으로 I/O를 구현하는 방식들을 잘 보여주는 예시이다. 논블럭 recv함수는 읽을 수 있는 데이터만 복사해서 가져오고 그 결과를 반환한다. 원하는 사이즈의 데이터를 받으려면 데이터를 축적하여 받아와야할 것이다. 함수가 반환하는 값에 따라서 적절하게 동작하도록 코딩하면 원하는 결과를 얻을 수 있을 것이다.

 

그렇다면 이제 Blocking 식 서버에서는 할 수 없었던 싱글 쓰레드 다중접속 서버를 만들 수 있다. accept된 소켓을 하나씩 클라이언트 세션으로 만들고 클라이언트 매니저가 연결된 클라이언트들을 관리한다. 클라이언트 매니저는 모든 클라이언트 세션들을 계속해서 순회하면서 recv를 호출하여 입력을 받는다. 그리고 받은 내용에 대한 처리를 해서 send로 응답해줄 수 있다. 이때 수행되는 작업이 Non-blocking이므로 따로 쓰레드를 만들지 않아도 충분히 잘 동작할 것이다. 이 구현방식의 문제는 클라이언트가 따로 입력을 하지 않아도 계속해서 recv로 확인을 해줘야한다는 점이다. 버퍼가 준비되었는지를 확인하는데 recv를 쓰는것은 리소스를 남용하는 것이다. recv말고 그냥 해당 소켓의 버퍼를 체크할 수 있는 방법이 있다면, 읽고 쓸 수 있는 상태에 처한 소켓들을 가려낼 수 있다면 더 효과적인 방법으로 서버를 만들 수 있을 것이다.

 

동기 비동기 I/O 통지모델


 

I/O 이벤트 통지 모델

이벤트 통지 모델은 Non-Blocking에서 제기된 문제를 해결하기 위해서 고안되었다. I/O처리를 할 수 있는 소켓(혹은 파일 디스크립터)을 가려내서 가르쳐준다면, 다시말해 입력 버퍼에 데이터가 수신되어서 데이터의 수신이 필요하거나, 출력버퍼가 비어서 데이터의 전송이 가능한 상황을 알려준다면, 위에서 이야기한 구조보다 더 단순하고 효과적으로 다중 I/O모델을 처리할 수 있을 것이다. I/O 이벤트를 통지하는 방법은 크게 동기형 통지모델과 비동기형 통지모델로 나눌 수 있다. 

 

동기형 통지모델

동기(synchronous)와 비동기(asynchronous)는 서로 메시지를 주고받는 상대방이 어떤 방식으로 통신을 하는가에 대한 개념이다. I/O 통지모델에서 대화하는 주체들은 커널과 프로세스이다. 프로세스는 커널에게 I/O처리를 요청하고,커널은 프로세스에게 I/O 상황을 통지한다. 우선 I/O 요청은 반드시 동일하게 처리될 수 밖에 없는 부분이고, 결국에 커널이 프로세스에게 어떤 방식으로 통지하느냐에 따라 동기형이냐 비동기형이 결정될 것이다. 

동기형 통지모델의 프로세스는 커널에게 지속적으로 현재 I/O 준비 상황을 체크한다. 즉 커널이 준비되었는지를 계속 확인하여 동기화 하는 것이다. 따라서 동기형 통지모델에서 Notify를 적극적으로 진행하는 주체는 유저의 프로세스가 되며 커널은 수동적으로 유저 프로세스의 요청에 따라 현재의 상황을 보고한다. 

 

비동기형 통지모델

이와 반대로 비동기형 통지모델은 일단 커널에게 I/O작업을 맡기면 커널의 작업 진행사항에 대해서 프로세스가 인지할 필요가 없는 상황을 말한다. 유저의 프로세스가 I/O 동기화를 신경쓸 필요가 없기에 비동기형이라고 부를 수 있다. 따라서 비동기형 통지모델에서 Notify의 적극적인 주체는 커널이 되며, 유저 프로세스는 수동적인 입장에서 자신이 할일을 하다가 통지가 오면 그때 I/O 처리를 하게 된다. 



출처: https://ozt88.tistory.com/20?category=123069 [공부 모음]

설정

트랙백

댓글

C언어) 간단하게 엑셀 파일로 저장하기

프로그래밍 언어 2019. 7. 10. 09:32

저런식으로 ,(콤마)로 칸을 구별하여 엑셀 파일로 저장할 수 있다.

확장자를 csv로 저장해야 한다.

설정

트랙백

댓글

C 예제) AES-128 ECB

Embedded/펌웨어? 2019. 6. 10. 16:47

아래 예제 소스이다.

 

메인에서

Data1 배열을 함수

AES_ECB_Encrypt(Data1, Key, EncBuff, Len); 

를 사용하여 암호화 된 데이터가 EncBuff에 저장되고

 

암호화된 데이터를 함수
AES_ECB_Decrypt(EncBuff, Key, DecBuff, Len); 

를 사용하면 DecBuff에 데이터가 나온다.

 

CBC 방식에 암호화 복호화 키 값은 좀 더 찾아봐야겠다.

 

 

예제)

// 여기부터 쭉 그냥 복사 시작 ------------------------------------------------------

#include  <stdio.h>
#include  <string.h>

#ifdef AES256
#define KEYLEN      32
#elif defined(AES192)
#define KEYLEN      24
#else
#define KEYLEN      16  //Key Length in unsigned chars
#endif

#define Nr          (KEYLEN/8+3)*2      //The number of rounds in AES Cipher.
#define KEYEXPSIZE  (Nr+1)*16
#define BLOCKLEN    16

#define SWAP(T,A,B)         {T=A; A=B; B=T;}
#define ROTATE(T,A,B,C,D)   {T=A; A=B; B=C; C=D; D=T;}


static const unsigned char SBox[256]=
{
    //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
    0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
    0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
    0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
    0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
    0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
    0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
    0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
    0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
    0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
    0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
    0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
    0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
    0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
    0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
    0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
};


static const unsigned char SBoxInvert[256]=
{
    0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
    0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
    0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
    0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
    0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
    0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
    0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
    0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
    0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
    0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
    0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
    0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
    0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
    0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
    0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
    0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
};




//-----------------------------------------------------------------------------
//The lookup-tables are marked CONST so they can be placed in read-only storage instead of RAM
//The numbers below can be computed dynamically trading ROM for RAM -
//This can be useful in (embedded) bootloader applications, where ROM is often limited.
//-----------------------------------------------------------------------------
void GetSBox(unsigned char * TA)
{
    TA[0]=SBox[TA[0]];
    TA[1]=SBox[TA[1]];
    TA[2]=SBox[TA[2]];
    TA[3]=SBox[TA[3]];
}




//This function produces 4*(Nr+1) round keys. The round keys are used in each round to decrypt the states.
void KeyExpansion(unsigned char * ExpKey, unsigned char * Key)
{
    int I, T;
    unsigned char TA[4];                 //Used for the column/row operations
    static const unsigned char Rcon[11]= //The round constant word array, Rcon[I], contains the values given by X to th e power (I-1) being powers of X (X is denoted as {02}) in the field GF(2^8)
    {
        0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
    };

    memcpy(ExpKey, Key, KEYLEN);

    //All other round keys are found from the previous round keys.
    for (I=KEYLEN; I<KEYEXPSIZE; I+=4)
    {
        memcpy(TA, ExpKey+I-4, 4);

        if (I % KEYLEN==0)
        {
            T=TA[0];
            TA[0]=TA[1];
            TA[1]=TA[2];
            TA[2]=TA[3];
            TA[3]=T;

            GetSBox(TA);

            TA[0]^=Rcon[I/KEYLEN];
        }
        #if defined(AES256)
        if (I % KEYLEN==16) GetSBox(TA);
        #endif
        ExpKey[I+0]=ExpKey[I-KEYLEN+0]^TA[0];
        ExpKey[I+1]=ExpKey[I-KEYLEN+1]^TA[1];
        ExpKey[I+2]=ExpKey[I-KEYLEN+2]^TA[2];
        ExpKey[I+3]=ExpKey[I-KEYLEN+3]^TA[3];
    }
}



//This function adds the round key to state.
//The round key is added to the state by an XOR function.
void AddRoundKey(unsigned char (*State)[4], unsigned char* ExpKey, unsigned char Round)
{
    int I, J;

    for (I=0; I<4; I++)
        for (J=0; J<4; J++) State[I][J]^=ExpKey[Round*4*4 + I*4 + J];
}



//The SubBytes Function Substitutes the values in the state matrix with values in an S-box.
void SubBytes(unsigned char (*State)[4])
{
    int I;

    for (I=0; I<4; I++) GetSBox(State[I]);
}



//The ShiftRows() function shifts the rows in the state to the left.
//Each row is shifted with different offset.
//Offset = Row number. So the first row is not shifted.
void ShiftRows(unsigned char (*State)[4])
{
    unsigned char T;

    ROTATE(T, State[0][1], State[1][1], State[2][1], State[3][1]);

    SWAP(T, State[0][2], State[2][2]);
    SWAP(T, State[1][2], State[3][2]);

    ROTATE(T, State[0][3], State[3][3], State[2][3], State[1][3]);
}



void InvShiftRows(unsigned char (*State)[4])
{
    unsigned char T;

    ROTATE(T, State[3][1], State[2][1], State[1][1], State[0][1]);

    SWAP(T, State[0][2], State[2][2]);
    SWAP(T, State[1][2], State[3][2]);

    ROTATE(T, State[0][3], State[1][3], State[2][3], State[3][3]);
}




int XTime(int X)
{
    return ((X<<1) & 0xFF) ^ (((X>>7)&1)*0x1B);
}



//MixColumns function mixes the columns of the state matrix
void MixColumns(unsigned char (*State)[4])
{
    int I, T1, T2;

    for (I=0; I<4; I++)
    {
        T1=State[I][0];
        T2=State[I][0]^State[I][1]^State[I][2]^State[I][3];
        State[I][0]^=XTime(State[I][0]^State[I][1])^T2;
        State[I][1]^=XTime(State[I][1]^State[I][2])^T2;
        State[I][2]^=XTime(State[I][2]^State[I][3])^T2;
        State[I][3]^=XTime(State[I][3]^T1)^T2;
    }
}



//Used to multiply numbers in the field GF(2^8)
int Multiply(int X, int Y)
{
    return ((Y>>0&1)*X)^
           ((Y>>1&1)*XTime(X))^
           ((Y>>2&1)*XTime(XTime(X)))^
           ((Y>>3&1)*XTime(XTime(XTime(X))))^
           ((Y>>4&1)*XTime(XTime(XTime(XTime(X)))));
}


//MixColumns function mixes the columns of the state matrix.
//The method used to multiply may be difficult to understand for the inexperienced.
//Please use the references to gain more information.
void InvMixColumns(unsigned char (*State)[4])
{
    int  I, A, B, C, D;

    for (I=0; I<4; I++)
    {
        A=State[I][0];
        B=State[I][1];
        C=State[I][2];
        D=State[I][3];

        State[I][0] = Multiply(A, 0x0E) ^ Multiply(B, 0x0B) ^ Multiply(C, 0x0D) ^ Multiply(D, 0x09);
        State[I][1] = Multiply(A, 0x09) ^ Multiply(B, 0x0E) ^ Multiply(C, 0x0B) ^ Multiply(D, 0x0D);
        State[I][2] = Multiply(A, 0x0D) ^ Multiply(B, 0x09) ^ Multiply(C, 0x0E) ^ Multiply(D, 0x0B);
        State[I][3] = Multiply(A, 0x0B) ^ Multiply(B, 0x0D) ^ Multiply(C, 0x09) ^ Multiply(D, 0x0E);
    }
}




//The SubBytes Function Substitutes the values in the state matrix with values in an S-box.
void InvSubBytes(unsigned char (*State)[4])
{
    int I, J;

    for (I=0; I<4; I++)
        for (J=0; J<4; J++) State[J][I]=SBoxInvert[State[J][I]];
}



void Cipher(unsigned char (*State)[4], unsigned char * ExpKey)
{
    int Round;

    //Add the First round key to the state before starting the rounds.
    AddRoundKey(State, ExpKey, 0);

    //There will be Nr rounds.
    //The first Nr-1 rounds are identical.
    //These Nr-1 rounds are executed in the loop below.
    for (Round=1; Round<Nr; Round++)
        {
        SubBytes(State);
        ShiftRows(State);
        MixColumns(State);
        AddRoundKey(State, ExpKey, Round);
        }

    //The last round is given below.
    //The MixColumns function is not here in the last round.
    SubBytes(State);
    ShiftRows(State);
    AddRoundKey(State, ExpKey, Nr);
}



void InvCipher(unsigned char (*State)[4], unsigned char* ExpKey)
{
    int Round;

    //Add the First round key to the state before starting the rounds.
    AddRoundKey(State, ExpKey, Nr);

    //There will be Nr rounds.
    //The first Nr-1 rounds are identical.
    //These Nr-1 rounds are executed in the loop below.
    for (Round=Nr-1; Round>0; Round--)
        {
        InvShiftRows(State);
        InvSubBytes(State);
        AddRoundKey(State, ExpKey, Round);
        InvMixColumns(State);
        }

    //The last round is given below.
    //The MixColumns function is not here in the last round.
    InvShiftRows(State);
    InvSubBytes(State);
    AddRoundKey(State, ExpKey, 0);
}



//-----------------------------------------------------------------------------
//          ECB
//-----------------------------------------------------------------------------
void AES_ECB_Encrypt(unsigned char * Input, unsigned char * Key, unsigned char * Output, int Length)
{
    unsigned char ExpKey[KEYEXPSIZE];

    memcpy(Output, Input, Length);
    KeyExpansion(ExpKey, Key);
    Cipher((unsigned char (*)[4])Output, ExpKey);
}


void AES_ECB_Decrypt(unsigned char* Input, unsigned char* Key, unsigned char* Output, int Length)
{
    unsigned char ExpKey[KEYEXPSIZE];

    memcpy(Output, Input, Length);
    KeyExpansion(ExpKey, Key);
    InvCipher((unsigned char (*)[4])Output, ExpKey);
}



//-----------------------------------------------------------------------------
//          CBC
//-----------------------------------------------------------------------------
void XorWithIv(unsigned char * Buff, unsigned char * Iv)
{
    int I;
    for (I=0; I<BLOCKLEN; I++) Buff[I]^=Iv[I];
}


void AES_CBC_Encrypt(unsigned char * Output, unsigned char * Input, int Length, unsigned char * Key, unsigned char * Iv)
{
    int I, Extra;
    unsigned char ExpKey[KEYEXPSIZE];

    Extra=Length % BLOCKLEN;
    KeyExpansion(ExpKey, Key);

    for (I=0; I<Length; I+=BLOCKLEN)
        {
        XorWithIv(Input, Iv);
        memcpy(Output, Input, BLOCKLEN);
        Cipher((unsigned char (*)[4])Output, ExpKey);
        Iv=Output;
        Input+=BLOCKLEN;
        Output+=BLOCKLEN;
        }

    if (Extra)
        {
        memcpy(Output, Input, Extra);
        Cipher((unsigned char (*)[4])Output, ExpKey);
        }
}


void AES_CBC_Decrypt(unsigned char * Output, unsigned char * Input, int Length, unsigned char * Key, unsigned char * Iv)
{
    int I, Extra;
    unsigned char ExpKey[KEYEXPSIZE];

    Extra=Length % BLOCKLEN;
    KeyExpansion(ExpKey, Key);

    for (I=0; I<Length; I+=BLOCKLEN)
        {
        memcpy(Output, Input, BLOCKLEN);
        InvCipher((unsigned char (*)[4])Output, ExpKey);
        XorWithIv(Output, Iv);
        Iv=Input;
        Input+=BLOCKLEN;
        Output+=BLOCKLEN;
        }

    if (Extra)
        {
        memcpy(Output, Input, Extra);
        InvCipher((unsigned char (*)[4])Output, ExpKey);
        }
}

// 여기까지 쭉 복사 끝 --------------------------------------------------------------


// 여기부터 메인 예제 ---------------------------------------------------------------

int main(int argc, char *argv[]) {
    int  I, Len;
    unsigned char Data[]={0x00, 0x0A, 0x11, 0x45, 0xEE, 0x90, 0xEE, 0x92, 0xEE, 0x91, 0x00, 0xF1, 0x21, 0xAA, 0x03, 0xFF};
    unsigned char Data1[]={0x00, 0x0A, 0x12, 0x44, 0xEE, 0x90, 0xEE, 0x92, 0xEE, 0x91, 0x00, 0x91, 0x34, 0x1A, 0xBB, 0xFF};
    unsigned char Data2[]={0x00, 0x0A, 0x13, 0x64, 0xEE, 0x90, 0xEE, 0x92, 0xEE, 0x91, 0x00, 0x84, 0x01, 0x1C, 0xC1, 0xFF};
    unsigned char Key[]={0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x47, 0x77, 0x11, 0x1E, 0x3c};
    unsigned char EncBuff[80];
    unsigned char DecBuff[80];
 
    printf("Testing AES128\n\n");
 
    Len = 16;
 
    // Hex 출력
    printf("Hex     :  ");
    for(I=0; I<Len; I++) printf("%02X ", Data[I]);
    
    // 암호화
    AES_ECB_Encrypt(Data, Key, EncBuff, Len);
    printf("\nEncorded: ");
    for (I=0; I<Len; I++) printf(" %02X", EncBuff[I]);
 
    // 복호화
    memset(DecBuff, 0, sizeof(DecBuff));
    AES_ECB_Decrypt(EncBuff, Key, DecBuff, Len);
    printf("\nDecorded:  ");
    for(I=0; I<Len; I++) printf("%02X ", DecBuff[I]);
printf("\n----------------------------------------------------------\n");


    // Hex 출력
    printf("Hex     :  ");
    for(I=0; I<Len; I++) printf("%02X ", Data1[I]);
    
    // 암호화
    AES_ECB_Encrypt(Data1, Key, EncBuff, Len);
    printf("\nEncorded: ");
    for (I=0; I<Len; I++) printf(" %02X", EncBuff[I]);
 
    // 복호화
    memset(DecBuff, 0, sizeof(DecBuff));
    AES_ECB_Decrypt(EncBuff, Key, DecBuff, Len);
    printf("\nDecorded:  ");
    for(I=0; I<Len; I++) printf("%02X ", DecBuff[I]);
printf("\n----------------------------------------------------------\n");


    // Hex 출력
    printf("Hex     :  ");
    for(I=0; I<Len; I++) printf("%02X ", Data2[I]);
    AES_ECB_Encrypt(Data2, Key, EncBuff, Len);
 
    // 암호화
    printf("\nEncorded: ");
    for (I=0; I<Len; I++) printf(" %02X", EncBuff[I]);
 
    // 복호화
    memset(DecBuff, 0, sizeof(DecBuff));
    AES_ECB_Decrypt(EncBuff, Key, DecBuff, Len);
    printf("\nDecorded:  ");
    for(I=0; I<Len; I++) printf("%02X ", DecBuff[I]);
printf("\n----------------------------------------------------------\n");
 
    return 0;

}

 

 

실행 화면

 

main.c
0.01MB

 

 

확인 사이트

http://aes.online-domain-tools.com/

 

AES Encryption – Easily encrypt or decrypt strings or files

Input text: (plain)

aes.online-domain-tools.com

'Embedded > 펌웨어?' 카테고리의 다른 글

ST-link v2 readout protection (RDP) 설정  (0) 2022.12.05
USBISP-MK2 Manual  (0) 2020.06.16
stm32f05xx CRC  (0) 2019.04.16

설정

트랙백

댓글