mirror of
https://salsa.debian.org/gnuk-team/gnuk/gnuk.git
synced 2024-09-19 18:30:15 +00:00
1ba3b76796
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
125 lines
4.1 KiB
Python
125 lines
4.1 KiB
Python
from time import time
|
|
from struct import pack
|
|
from hashlib import sha1, sha256
|
|
from pk_25519_with_libgcrypt import fixup_scalar_cv25519, call_pk_sign, call_pk_encrypt, call_pk_verify
|
|
from card_const import KEY_ATTRIBUTES_CV25519, KEY_ATTRIBUTES_ED25519
|
|
|
|
class PK_Crypto(object):
|
|
@staticmethod
|
|
def pk_from_pk_info(pk_info):
|
|
return b'\x40' + pk_info[5:]
|
|
|
|
@staticmethod
|
|
def compute_digestinfo(msg):
|
|
return sha256(msg).digest()
|
|
|
|
@staticmethod
|
|
def enc_data(enc_info):
|
|
return b'\xa6\x25\x7f\x49\x22\x86\x20' + enc_info[1]
|
|
|
|
@staticmethod
|
|
def enc_check(enc_info, s):
|
|
return enc_info[0] == s
|
|
|
|
|
|
def __init__(self, keyno=None, pk_info=None, data=None):
|
|
if keyno == None:
|
|
# Just for name space
|
|
return
|
|
|
|
self.keyno = keyno
|
|
self.for_encryption = (self.keyno == 1)
|
|
self.timestamp = pack('>I', int(time()))
|
|
if pk_info:
|
|
# Public part only (no private data) from card
|
|
self.q = pk_info[5:]
|
|
else:
|
|
if self.for_encryption:
|
|
# Private part (in big endian), while DATA is native (little) endian
|
|
d = data[0]
|
|
self.d = fixup_scalar_cv25519(d)
|
|
else:
|
|
# Private part (in little (native) endian)
|
|
self.d = data[0]
|
|
self.q = data[1]
|
|
self.fpr = self.calc_fpr()
|
|
|
|
def calc_fpr(self):
|
|
m_len = 6 + 2 + 33
|
|
ver = b'\x04'
|
|
algo = b'\x12' if self.for_encryption else b'\x16'
|
|
m = b'\x99' + pack('>H', m_len) + ver + self.timestamp + algo \
|
|
+ pack('>H', 256+7) + b'\x40' + self.q
|
|
return sha1(m).digest()
|
|
|
|
def build_privkey_template(self, is_yubikey):
|
|
openpgp_keyno = self.keyno + 1
|
|
if openpgp_keyno == 1:
|
|
keyspec = b'\xb6'
|
|
elif openpgp_keyno == 2:
|
|
keyspec = b'\xb8'
|
|
else:
|
|
keyspec = b'\xa4'
|
|
key_template = b'\x92\x20'
|
|
exthdr = keyspec + b'\x00' + b'\x7f\x48' + b'\x02' + key_template
|
|
suffix = b'\x5f\x48' + b'\x20'
|
|
return b'\x4d' + b'\x2a' + exthdr + suffix + self.d
|
|
|
|
def compute_signature(self, digestinfo):
|
|
return call_pk_sign(self.d, digestinfo)
|
|
|
|
def verify_signature(self, digestinfo, sig):
|
|
return call_pk_verify(self.q, digestinfo, sig)
|
|
|
|
def encrypt(self, plaintext):
|
|
# Do ECDH
|
|
return call_pk_encrypt(self.q, plaintext)
|
|
|
|
def get_fpr(self):
|
|
return self.fpr
|
|
|
|
def get_timestamp(self):
|
|
return self.timestamp
|
|
|
|
def get_pk(self):
|
|
return b'\x40' + self.q
|
|
|
|
key = [ None, None, None ]
|
|
|
|
ed25519_data = (b'\x83\x3f\xe6\x24\x09\x23\x7b\x9d\x62\xec\x77\x58\x75\x20\x91\x1e'
|
|
b'\x9a\x75\x9c\xec\x1d\x19\x75\x5b\x7d\xa9\x01\xb9\x6d\xca\x3d\x42',
|
|
b'\xec\x17\x2b\x93\xad\x5e\x56\x3b\xf4\x93\x2c\x70\xe1\x24\x50\x34'
|
|
b'\xc3\x54\x67\xef\x2e\xfd\x4d\x64\xeb\xf8\x19\x68\x34\x67\xe2\xbf')
|
|
|
|
cv25519_data = (b'\x77\x07\x6d\x0a\x73\x18\xa5\x7d\x3c\x16\xc1\x72\x51\xb2\x66\x45'
|
|
b'\xdf\x4c\x2f\x87\xeb\xc0\x99\x2a\xb1\x77\xfb\xa5\x1d\xb9\x2c\x2a',
|
|
b'\x85\x20\xf0\x09\x89\x30\xa7\x54\x74\x8b\x7d\xdc\xb4\x3e\xf7\x5a'
|
|
b'\x0d\xbf\x3a\x0d\x26\x38\x1a\xf4\xeb\xa4\xa9\x8e\xaa\x9b\x4e\x6a')
|
|
|
|
key[0] = PK_Crypto(0, data=ed25519_data)
|
|
key[1] = PK_Crypto(1, data=cv25519_data)
|
|
key[2] = PK_Crypto(2, data=ed25519_data)
|
|
|
|
PLAIN_TEXT0=b"This is a test message."
|
|
PLAIN_TEXT1=b"cryptography is as easy as pie."
|
|
|
|
ENCRYPT_TEXT0 = sha256(b"encrypt me please").digest()
|
|
ENCRYPT_TEXT1 = sha256(b"encrypt me please, another").digest()
|
|
ENCRYPT_TEXT2 = sha256(b"encrypt me please, the other").digest()
|
|
|
|
test_vector = {
|
|
'sign_0' : PLAIN_TEXT0,
|
|
'sign_1' : PLAIN_TEXT1,
|
|
'auth_0' : PLAIN_TEXT0,
|
|
'auth_1' : PLAIN_TEXT1,
|
|
'decrypt_0' : ENCRYPT_TEXT0,
|
|
'decrypt_1' : ENCRYPT_TEXT1,
|
|
'encrypt_0' : ENCRYPT_TEXT2,
|
|
}
|
|
|
|
curve25519_pk = PK_Crypto()
|
|
curve25519_pk.test_vector = test_vector
|
|
curve25519_pk.key_list = key
|
|
curve25519_pk.key_attr_list = [KEY_ATTRIBUTES_ED25519, KEY_ATTRIBUTES_CV25519, KEY_ATTRIBUTES_ED25519]
|
|
curve25519_pk.PK_Crypto = PK_Crypto
|