현대 암호학

[현대 암호학] 06. 실습(2)

Uggjjini 2021. 6. 28. 18:15

[실습] ECDSA 사용한 전자서명 구현하기

 

DSA(Digital Signature Authentication)

광범위한 공개 키 서명 알고리즘이다. 보안은 이산 로그 문제(DLP)를 기반으로 한다.

 

 

DSA key 생성(private key, public key) 생성

DSAKeyGen.py

from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
from Crypto.Hash import SHA256

# 새로운 DSA key 생성
prikey = DSA.generate(2048)
print(prikey)

pubkey = prikey.publickey().export_key()
print(pubkey)

 

<DsaKey @0x7ff882656e20 y,g,p(2048),q,x,private>
b'-----BEGIN PUBLIC KEY-----\nMIID ..... A2Ns=\n-----END PUBLIC KEY-----'

 

 

DSA 서명(signature)/검증(verification)

DSASigVerify.py

from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
from Crypto.Hash import SHA256

#
# (1) Signature(signer)
#
# sender : message, private key => signature, public key

# 새로운 DSA private/public key 생성
prikey = DSA.generate(2048)
with open('public_key.pem', 'wb') as fd1:
    fd1.write(prikey.publickey().export_key('PEM'))

# private key로 메세지에 sign(=> 메세지의 해시 값에 sign)
message = b'hello'
hash = SHA256.new(message)
signer = DSS.new(prikey, 'fips-186-3')
signature = signer.sign(hash)

print('sender: message:', message)
print('sender: signature:', signature)


#
# (2) Verification(verifier)
#
# receiver : message, public key, signature
# public keys는
# * 일반적으로 상대편에게 받거나 인터넷에서 받는다.
# * 실습에서는 직접 작업하였다.

# 받은 message & signature
received_msg = b'hello'
received_signature = signature

# public key 읽기
with open('public_key.pem', 'rb') as fd2:
    pubkey = DSA.import_key(fd2.read())
# 해시 값 계산
hash = SHA256.new(received_msg)
try:
    verifier = DSS.new(pubkey, 'fips-186-3')
    verifier.verify(hash, received_signature)
    print('[  OK  ] : Authentic')
except Exception as e:
    print('[ FAIL ] : Not authentic')

sender: message: b'hello'
sender: signature: b'x\xb4\xa3{O\\e\x82~\xf3\t\xa4$5\x19D\x92c\xfe\xc6\xa8X\x9f\x0e\x06f\x00:<J\x...
[  OK  ] : Authentic

 

 

ECC(Elliptic Curve Cryptography)

  • 현대적이고 효율적인 유형의 공개 키 암호이다.
  • 보안은 곡선을 통해 계산된 특정 방정식으로 정의 된 필드에서 이산 로그를 풀기가 어렵다는 점을 기반으로 한다.
  • ECC를 사용하여 ()디지털 서명을 만들거나 ()키 교환을 수행 할 수 있다.

 

곡선(Curve) 가능한 식별자
NIST P-256 'NIST P-256', 'p256', 'P-256', 'prime256v1', 'secp256r1'
NIST P-384 'NIST P-384', 'p384', 'P-384', 'prime384v1', 'secp384r1'
NIST P-521 'NIST P-521', 'p521', 'P-521', 'prime521v1', 'secp521r1'

 

새로운 ECC 키를 생성하고, export 하여 애플리케이션이 다시 load 하기

ECCKeyGen.py

from Crypto.PublicKey import ECC

# private key
prikey = ECC.generate(curve='P-256')

fd = open('myprivatekey.pem', 'wt')
fd.write(prikey.export_key(format='PEM'))
fd.close()

# public key
pubkey = prikey.public_key()
print(pubkey)

fd2 = open('myprivatekey.pem', 'rt')
pubkey2 = ECC.import_key(fd2.read())
print(pubkey2)
EccKey(curve='NIST P-256', point_x=9161398...30652996, point_y=26279...868669099873277895926335481816144)
EccKey(curve='NIST P-256', point_x=9161398...30652996, point_y=26279....861843453652545878903239)

 

 

ECDSA 전자 서명 구현하기

 

ECDSA = ECC + DSA

 

ECDSA 사용한 전자서명 구현하기

ECDSA 방식을 사용하여 전자서명을 구현해 보자.

 

 

ECDSA 대해서

  • RSA는 1994년 표준화된 공개키 암호로 현재까지 광범위하게 오랫동안 사용되어온 기술이다.
  • ECDSA는 타원 곡선 기반의 전자서명 알고리즘으로 비교적 최근인 2008년 TLS v1.2의 기술 명세서에 소개된 공개키 암호 체계이다.
  • 동일한 보안 수준으로 비교할 때 ECDSA는 RSA 보다 휠씬 작은 key size 갖는다.
  • 예를 들어, 3072비트 key size RSA는 768바이트 데이터 크기를 가지지만, 동일한 보안 수준의 ECDSA는 RSA의 1/24 크기인 32바이트 데이터 크기를 가진다.
  • RSA와 ECDSA의 성능을 비교해 볼때, 서명 속도RSA가 ECDSA에 비해 빠르지만, 서명을 검증하는 속도ECDSA가 RSA보다 빠르다.

 

ECDSASign.py

from Crypto.PublicKey import ECC
from Crypto.Signature import DSS
from Crypto.Hash import SHA256 as SHA
import os


def createPEM_ECDSA():
    # ECC.generate : 타원곡석암호를 이용해 개인키를 생성한다.
    # 'P-256' : (권장) 타원곡선암호를 만들기 위한 상수
    key = ECC.generate(curve='P-256')
    with open('privatekey_ecdsa.pem', 'w') as h:
        h.write(key.export_key(format='PEM'))

    key = key.public_key()
    with open('publickey_ecdsa.pem', 'w') as h:
        h.write(key.export_key(format='PEM'))


def readPEM_ECC(pemfile):
    with open(pemfile, 'r') as h:
        key = ECC.import_key(h.read())

    return key


def ecdsa_sign(msg):
    private_key = readPEM_ECC('privatekey_ecdsa.pem')
    sha = SHA.new(msg)
    signer = DSS.new(private_key, 'fips-186-3')
    signature = signer.sign(sha)

    return signature


def ecdsa_verify(msg, signature):
    public_key = readPEM_ECC('publickey_ecdsa.pem')
    sha = SHA.new(msg)
    verifier = DSS.new(public_key, 'fips-186-3')
    try:
        verifier.verify(sha, signature)
        print('Authentic')
    except ValueError:
        print('Not authentic')


def main():
    if os.path.exists('privatekey_ecdsa.pem') and os.path.exists('publickey_ecdsa.pem'):
        print('privatekey_ecdsa.pem, publickey_ecdsa.pem file exist')
    else:
        createPEM_ECDSA()
        print('privatekey_ecdsa.pem, publickey_ecdsa.pem file created.')

    msg = 'My name is samsjang'
    signature = ecdsa_sign(msg.encode('utf-8'))
    ecdsa_verify(msg.encode('utf-8'), signature)


if __name__ == '__main__':
    main()