♣ 도움받은 사이트

https://8gwifi.org/docs/python-rsa.jsp

https://stackoverflow.com/questions/21327491/using-pycrypto-how-to-import-a-rsa-public-key-and-use-it-to-encrypt-a-string

 

♣  Python 에서 RSA 를 사용하기 위해 아래와 같이 pycryot를 설치하였다.

1. pycropto 설치 (Linux)

https://pypi.python.org/pypi/pycrypto 에서 모듈을 다운받는다.

아래와 같이 설치한다.

$ sudo python3 setup.py install

 

설치하면... time.clock() 함수가 없다고 뜬다.

찾아보니 Python 3.8 부터 위 함수가 폐기됐다고 한다. 아오~~

결국 Python 2.7 에서 설치하였다.

 

리눅스에서

$ python -> 2.7

$ python3 -> 3.8 로 실행되기에 python 으로 실행했다.

 

♣  Python 에서 Public Key, Private Key 생성하기

Public Key, Priavte 키 생성 (PEM 방식)

from Crypto.PublicKey import RSA

#Export RSA public/private KEY in PEM format
key = RSA.generate(2048)
privKey = key.exportKey('PEM')
pubKey = key.publickey().exportKey('PEM')

 

#save PEM key into the file
with open('private.pem', 'w') as file:
        file.write(privKey)
        file.write('\n')

 

with open('public.pem', 'w') as file:
        file.write(pubKey)
        file.write('\n')

 

테스트를 위해 plain.txt 파일을 만들고 아래와 같이 내용을 추가한다. (변경 가능0

Open SSL, Python Test

 

♣  OpenSSL 로 키 테스트

Python에서 생성한 키로  OpenSSL 에서 테스트해 본다.

 

1. Public key 로 암호화하기

 $ openssl rsautl -encrypt -inkey ./public.pem -pubin -in ./plain.txt -out encrypt.txt

 

2. Private Key 로 복호화하기

 $ openssl rsautl -decrypt -inkey private.pem -in encrypt.txt -out decPlain.txt

 

3. plain.txt 와 decPalin.txt 의 내용이 같은지 확인해 본다.

 

♣  Python 에서 Public Key 로 암호화 하기.

위에서 생성한 public key 로 아래와 같이 암호화 해 본다.

 

Encrypt Plain Text by public key

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5

fPri = open('private.pem', 'rb')
fPub = open('public.pem', 'rb')

 

prikey = RSA.importKey(fPri.read())
pubKey = RSA.importKey(fPub.read())

 

#RSA Encryption Using Public Key
fp = open('plain.txt', 'rb')

cipherKey = Cipher_PKCS1_v1_5.new(pubKey)
cipherText = cipherKey.encrypt(fp.read())

 

fEnc = open('encrypt.txt', 'wb')
fEnc.write(cipherText)

 

# archive
#cipherText = pubKey.encrypt(fp.read(),32)
#cipherMsg = cipherText[0]


fPri.close()
fPub.close()
fp.close()
fEnc.close()

위에서 암호화 한 문장 (encrypt.txt) 을 openSSL 에서 복호화할 수 있다.

 

♣ Python 에서 Private Key 로 복호화 하기.

위에서 생성한 Private Key 로 아래와 같이 복호화 한다.

 

from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5 as Cipher_PKCS1_v1_5

fPri = open('private.pem', 'rb')

prikey = RSA.importKey(fPri.read())

 

#RSA Encryption Using Public Key
fEnc = open('encrypt.txt', 'rb')

cipher = Cipher_PKCS1_v1_5.new(prikey)
cipherText = cipher.decrypt(fEnc.read(), None).decode()

 

fDec = open('decPlain.txt', 'wb')
fDec.write(cipherText)

 

fPri.close()
fEnc.close()
fDec.close()

저 위의 OpenSSL 에서 암호화 한 후,

Python 에서 위와 같이 복호화하면 동일하게 복호화 되었다.

도움받은 사이트 : https://developer.zebra.com/thread/34694

 

ZPL 의 ^GF 명령어를 통해 Bitmap 데이터를 조합해 Zebra 프린터로 출력할 수 있습니다.

아래는 Bitmap 파일을 읽어 Zebra 프린터로 출력하기 위한 ZPL 코드를 생성하는 방법을 정리합니다.

 

테스트는 Visual Sutdio 2015 Express 에서 진행했으며

아래 test() 함수는 BMP 헤더 구조체만 정의하면 리눅스에서도 사용할 수 있을겁니다.

 

 

♣ Bitmap 이미지 생성

Zebra 프린터는 흑백으로 출력합니다.

이에 출력하려는 bmp 이미지를 단색만 사용하도록 설정합니다.

저는 윈도우 그림판에서

  1. 메뉴
  2. 다른이름으로 저장
  3. BMP 그림 선택
  4. 아래 파일형식 : 단색 비트맵 (~~) 선택

으로 저장합니다.

 

 

첨부파일 hosang.bmp 는 위 이미지를 단색으로 저장하였고 크기는 67x32 입니다.

(※ hosang.bmp 파일은 아래 이미지를 우클릭해서 다른이름으로 저장하여 사용하시기 바랍니다.)

 

  -> 이거 우클릭 후, 저장~

 

 

 

♣ Bitmap Padding

단색 Bitmap 의 경우, 한 pixel 을 저장하는데 한 bit 를 소모합니다.

한 Byte는 8bits 이니 위 이미지의 한줄인 67 픽셀을 저장하는데 72 Bits ( 9 Bytes) 가 소모될 겁니다.

 

하지만 실제 파일을 열어보면 80 Bits (10 Bytes) 가 사용됩니다.

즉 단색 bitmap 은 16 bits ( 2 Bytes) 단위로 끊어 처리합니다.

 

 

실제 이미지 크기는 67 x 32 이지만,

bmp 파일에 저장된 이미지 영역은 80 x 32 입니다.

이 때 80 은 16 의 배수입니다.

 

즉 파일의 이미지 데이터 영역은 80x32 / 8 = 320 Bytes 가 됩니다

 

이에 bmp Info 에서 실제 width (67px) 를 얻어 68~80 번째 데이터는 무시하는 작업이 필요합니다.

 

그리고 상하로 뒤집어 저장하는 bmp 의 이미지 데이터를 다시 원래대로 돌려 놓습니다.

 

♣ ZPL Code

ZPL 코드로 Bitmap 처리를 하기 위해선 ^GF 명령어를 이용합니다.

( ^GF 관련 설명은 Zebra 사의 ZPL 설명서 참조)

본 글은 ^GF 의 마지막 항목인 데이터 영역을 만들기 위함입니다.

 

아래 test() 함수는 단색 타입의 bmp 파일을 읽어 ZPL 의 Data 영역을 만드는 함수입니다.

 

 

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
int test()
{
    string strZpl ;
    char szText[128] ;
    char szBmp[32] ;
 
    BITMAPFILEHEADER bmFile ;
    BITMAPINFOHEADER bmInfo ;
 
    int px = 100 ;
    int py = 100 ;
 
    FILE* fpBmp = fopen("./hosang.bmp""rb") ;
 
    if(!fpBmp)
    {
//        MyLog("genBitmap fopen Error\r\n") ;
        return -1 ;
    }
 
    // read BMP Header and Infomation.
    fread(&bmFile, sizeof(BITMAPFILEHEADER), 1, fpBmp) ;
    fread(&bmInfo, sizeof(BITMAPINFOHEADER), 1, fpBmp) ;
 
    // Move Image Data offset.
    fseek(fpBmp, bmFile.bfOffBits, SEEK_SET) ;
 
    strZpl.clear() ;
    strZpl += "^XA" ;
 
    sprintf(szText, "^FO%d,%d", px, py) ;
    strZpl += szText ;
 
    int width = ((bmInfo.biWidth / 32) + 1) * 4 ;
    int mod = (bmInfo.biWidth) % 32 ;
    int realWidth = (bmInfo.biWidth + 7) / 8 ;
 
    int imageSize = realWidth * bmInfo.biHeight ;
    int shiftCount = 0 ;
 
    sprintf(szText, "^GFA,%d,%d,%d,", imageSize, imageSize, realWidth) ;
    strZpl += szText ;
 
    list<string>         listRow ;
    list<string>::iterator     listRowIter ;
 
    string strRow ;
 
    for(int ii = 0; ii < bmInfo.biHeight; ii++)
    {
        strRow.clear() ;
        for(int jj = 1; jj <= width; jj++)
        {
            fread(szBmp, 1, 1, fpBmp) ;
 
            if(jj > realWidth)
                continue ;
 
            if(jj == realWidth)
            {
                shiftCount = 8 - ((bmInfo.biWidth + 8) % 8) ;
                for(int kk = 0; kk < shiftCount; kk++)
                {
                    szBmp[0] |= ((szBmp[0] >> kk) | 0x01) ;
                }
            }
 
            szBmp[0] ^= 0xff ;
            szBmp[1] = '\0' ;
            sprintf(szText, "%02X", szBmp[0] & 0xff) ;
            strRow += szText ;
        }
 
        listRow.push_front(strRow) ;
    }
 
    listRowIter = listRow.begin() ;
    for(; listRowIter != listRow.end(); listRowIter++)
    {
        strZpl += *listRowIter ;
    }
    fclose(fpBmp) ;
 
    strZpl += "^FS";
    strZpl += "^XZ" ;
    
    FILE* fpZpl = fopen("./myZpl.txt""wt") ;
    fprintf(fpZpl, "%s", strZpl.c_str()) ;
    fclose(fpZpl) ;
 
    return 1 ;
}

 

위 함수가 실행되면 myZpl.txt 파일에 ZPL 코드가 아래와 같이 저장됩니다.

보기 편하게 줄로 나누어 봤습니다.

유효한 값에 형광펜을 칠해보면 이미지의 모양이 보입니다.

 

myZpl.txt

------------------------------------------

^XA^FO100,100^GFA,288,288,9,

0007C0000000003C00
0007C000001E003C00
0007C000001E003C00
0007C000001E003C00
1FFFFFF0001E003C00
1FFFFFF0001E003C00
1FFFFFF0001E003C00
1FFFFFF0001F003C00
00000000003F003FFE
001FF000007F803FFE
00FFFE00007FC03FFE
01FFFF0000F3E03FFE
03FFFF8001F1F83C00
07E00FC007E0FE3C00
078003C00FC07C3C00
078003C01F803C3C00
078003C00F00083C00
078007C00400003C00
07E00FC00000000000
03FFFF800001FF0000
01FFFF00000FFFE000
003FF800003FFFF000
0007C000007FFFF800
0007C000007E00FC00
0007C00000F8003C00
FFFFFFFE00F8003C00
FFFFFFFE00F8003C00
FFFFFFFE007E00FC00
FFFFFFFE007FFFF800
00000000003FFFF000
00000000000FFFE000
000000000001FF0000

^FS^XZ

 

위 ZPL 코드를 Zebra 프린터 (필자의 경우, ZM400 300dpi) 로 전송하면 아래와 같이 이미지가 출력됩니다.

 

 

 

 

 

 

 

 

 

 

(본 글은 Zebra 사의 Zebra Programming Guide 문서를 가지고 작성하였습니다.)

 

테스트 프린터 : ZM400, ZT410

 

본 글은 ZPL 에서 영어 이외의 글자. 예를 들어 스페인어 독일어, 체코어 등을 표시하는 법을 다룹니다.

ë, ß, Ä, é

뭐, 이런 글자들입니다.

 

예를 들어, 프랑스어 Référence 를 출력하는 코드는 아래와 같습니다.

^XA
^CI0
^FO80,70 ^A0N,30,30
^FH^FD R_82f_82rence SCF^FS
^XZ

 

위 문서에 보면 프랑스어는 Zebra Code Page 850 에 정의되어 있습니다.

그리고 é 는 Hex값으로 82 정의되어 있습니다.

 

 

 

 

위와 같이 특수문자는 정의된 Hex 값 앞에 _ 를 붙여 표시할 수 있습니다.

 

CI0 는 Zebra Code page 850 을 사용하겠다는 의미입니다. (문서의 ^CI 참조)

 

 

만약 체코어를 출력하게되면 어떻게 해야할까요?

Čeština 와 같이 말입니다.

 

위 Zebra Code page 850 에선 Č, š 와 같은 문자를 찾을 수 없습니다.

이 문자는 Zebra Code page 1250 에 정의되어 있습니다.

 

 

 

 

프랑스어와 같이 출력하면 아래와 같은 코드가 됩니다.

이 때 주의할 점은 ^CI31 로 값이 주어집니다.

이는 위 문서에 의해, Zebra Code page 1250 을 사용하기 위해선 CI31 로 세팅하라고 명시되어 잇습니다.

 

 ^XA
^CI31
^FO80,70 ^A0N,30,30
^FH^FD _c8e_9atina SCF^FS
^XZ

 

이렇게 간단히 특수문자를 출력하는 방법을 알아보았습니다.

도움받은 사이트 : https://stackoverflow.com/questions/33615048/what-zpl-codes-could-affect-the-start-position-of-a-qrcode

 

프린터 : ZM400, ZT410

 

아래는 간단한 QR Code 를 출력하는 ZPL 코드입니다.

 

^XA

^FO 0,0

^BQ N,2,15
^FDMA,hahaite^FS

^XZ

그런데 어쩔 때 보면 위와 같이 좌표를 0,0으로 주었는데도 QR Code 상단에 여백이 생기는 경우가 발생합니다.

예상 위치보다 더 아래에 출력된다는거죠.

 

웃긴게 이게 막 왔다갔다 하더라는거죠. 어떤날은 여백이 요만큼인데 어떤날은 여백이 이만큼인...

 

이래저래 찾아보니 이전에 출력한 바코드가 영향을 주는 듯 하더군요.

 

위 링크 사이트를 참고하여, QRCode 출력 전 dummy 바코드 하나 추가하니 해결되었습니다.

 

^XA

^BY,,1

^FO 0,0

^BQ N,2,15
^FDMA,hahaite^FS

^XZ 

 

 

 

예전 싸이월드 블로그에 작성한 글을 티스토리로 옮김.

싸이블로그 링크 : http://cy.cyworld.com/home/21147242/post/4EE70E1794D5739A07C68401

원문 작성일 : 2011년 12월 23일

 

================================================================

도움 받은 사이트 : http://apollo89.tistory.com/173
프로젝트 진행중에 컴파일을 하면
driver 하위 디렉토리들이 자기 밑에 objs 라는 디렉토리를 수십개 생성해버림.


drvier/audio/objs
drvier/audio/src/objs
drvier/video/objs
drvier/video/src/objs


갯수가 적으면 그려려니 하겠는데, 수십개가 뜨다보니
svn st 하면


? drvier/audio/objs
? drvier/audio/src/objs
? drvier/video/objs
? drvier/video/src/objs
 .............


해서 화면을 뒤덮어버림. ;;;;;;
전에 선임이 svn ignore 를 쓰던 기억이 떠올라 찾아봄.
별 생각없이 덤볐는데 의외로 사용법이 까칠하여 이것저것 정리해 봄.
svn propset (또는 svn ps ) 를 이용하는 방법과,
svn propedit (또는 svn pe ) 를 이용하는 방법이 있다.


♣ svn propset 성공 사례 - 1

$ svn propset svn:ignore objs ./driver/audio/
$ svn propset svn:ignore objs ./driver/audio/src/
$ svn propset svn:ignore objs ./driver/video/
$ svn propset svn:ignore objs ./driver/video/src/
$ svn st


이러고 제대로 되었는지 확인.


♣ svn propset 실패 사례 - 1
$ svn propset svn:ignore


./driver/audio/objs ./

 


♣ svn propset 실패 사례 - 2
$ svn propset svn:ignore


objs objs2


./driver/audio/src/


// 한번에 하나씩


♣ svn propset 실패 사례 - 3
$ svn propset svn:ignore objs ./ -R

// Recursive 안됨. ;;;


♣ svn propedit 성공 사례 - 1

$ svn propedit svn:ignore driver/audio/


(편집창 뜨면)
objs
(저장하고 나옴.)
이렇게 나머지 세 디렉토리를 일일이 해 주어야 함.


♣ svn propedit 실패 사례

$ svn propedit svn:ignore ./
(편집창 뜨면)


driver/audio/
driver/audio/src/
driver/video/
driver/video/src/


(저장하고 나옴.)


(이렇게 하니 안됨)


일단 이렇게 해서 수십개의 objs 디렉토리를 일일이 svn propset svn:ignore 명령어로
무시시켜버림.
svn st 하니 깔끔해서 좋다.
찜찜한게, 이렇게 노가다를 해야하는건가? 뭔가 좋은 방법이 숨어있을 것 같은 느낌이...

 

 

나도 함 github 써보고자 들어가서 계정 만들고 repository 도 만들고~

 

그러다 push 할 때마다 id, password 넣는게 귀찮아서 ssh 키 연동을 찾아 봄.

 

github 소개랑 ssh 키 생성은 검색하면 많이 나오고 아래는 그 외 사항을 잊지않으려 추가한 정도이다.

(나는 이미 예전에 생성한 ssh 키를 사용하고 있다.)

 

1. clone 시, https 가 아니라 ssh 로 시작하는 주소로 clone 해야 한다.

ssh 주소는 아래 useSSH 키 누르면 확인할 수 있다.

 

 

 

2. ~/.ssh/config 를 설정하고 있다면,

host 를 github.com 으로 바꾸어야 한다.

 

 

3. 아래 명령어로 ssh key 의 연동을 확인할 수 있다.

$ ssh -T git@github.com

Hi hahaite! You've successfully authenticated, but GitHub does not provide shell access

 

와 같이 출력되면 된다.

 

위와 같이 하니 수정 후, push 할 때 바로 서버로 전송되었다.

 

+ Recent posts