Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3 compatible key2pub.py #6

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 113 additions & 110 deletions utils/key2pub.py
Original file line number Diff line number Diff line change
@@ -1,129 +1,133 @@
#!/usr/bin/env python

#!/usr/bin/env python

import io
import sys
try:
from M2Crypto import RSA
except ImportError, e:
sys.stderr.write('ERROR: Failed to import the "M2Crypto" module: %s\n' % e.message)
sys.stderr.write('Please install the "M2Crypto" Python module.\n')
sys.stderr.write('On Debian GNU/Linux the package is called "python-m2crypto".\n')
sys.exit(1)

from Cryptodome.PublicKey import RSA
except ImportError as e:
sys.stderr.write('ERROR: Failed to import the "Cryptodome.PublicKey" module: %s\n' % e.message)
sys.stderr.write('Please install the "pycryptodomex" Python module.\n')
sys.stderr.write('Run 'pip install pycryptodomex' as ${USER} \n')
sys.exit(1)


def bitwise_collect(value, radix_bits):
words = []
radix_mask = (1 << radix_bits) - 1
while value != 0:
words.append(value & radix_mask)
value >>= radix_bits
return words

def print_ssl_64(output, name, val):
while val[0] == '\0':
val = val[1:]
while len(val) % 8:
val = '\0' + val
vnew = []
while len(val):
vnew.append((val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7]))
val = val[8:]
vnew.reverse()
output.write('static BN_ULONG %s[%d] = {\n' % (name, len(vnew)))
# OpenSSL expects 64-bit words given least-significant-word first.
vwords = bitwise_collect(val, 64)

output.write(u'static BN_ULONG {}[] = {{\n'.format(name))
idx = 0
for v1, v2, v3, v4, v5, v6, v7, v8 in vnew:
if not idx:
output.write('\t')
output.write('0x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x, ' % (ord(v1), ord(v2), ord(v3), ord(v4), ord(v5), ord(v6), ord(v7), ord(v8)))
idx += 1
if idx == 2:
for vword in vwords:
if not idx:
output.write(u'\t')
output.write(u'0x{:016x}ULL, '.format(vword))
idx += 1
if idx == 2:
idx = 0
output.write('\n')
output.write(u'\n')
if idx:
output.write('\n')
output.write('};\n\n')

output.write(u'\n')
output.write(u'};\n\n')
def print_ssl_32(output, name, val):
while val[0] == '\0':
val = val[1:]
while len(val) % 4:
val = '\0' + val
vnew = []
while len(val):
vnew.append((val[0], val[1], val[2], val[3], ))
val = val[4:]
vnew.reverse()
output.write('static BN_ULONG %s[%d] = {\n' % (name, len(vnew)))
# OpenSSL expects 32-bit words given least-significant-word first.
vwords = bitwise_collect(val, 32)

output.write(u'static BN_ULONG {}[] = {{\n'.format(name))
idx = 0
for v1, v2, v3, v4 in vnew:
for vword in vwords:
if not idx:
output.write('\t')
output.write('0x%.2x%.2x%.2x%.2x, ' % (ord(v1), ord(v2), ord(v3), ord(v4)))
output.write(u'\t')
output.write(u'0x{:08x}, '.format(vword))
idx += 1
if idx == 4:
idx = 0
output.write('\n')
output.write(u'\n')
if idx:
output.write('\n')
output.write('};\n\n')

output.write(u'\n')
output.write(u'};\n\n')
def print_ssl(output, name, val):

output.write(u'#include <stdint.h>\n')
output.write(u'#include <openssl/bn.h>\n')

import struct
output.write('#include <stdint.h>\n')
if len(struct.pack('@L', 0)) == 8:
return print_ssl_64(output, name, val)
else:
return print_ssl_32(output, name, val)

def print_ssl_keys(output, n):
output.write(r'''
struct pubkey {
struct bignum_st e, n;
};

#define KEY(data) { \
.d = data, \
.top = sizeof(data)/sizeof(data[0]), \
}

#define KEYS(e,n) { KEY(e), KEY(n), }

static struct pubkey keys[] = {
''')
output.write(u'''
struct pubkey {
struct bignum_st e, n;
};
#define KEY(data) { \\
.d = data, \\
.top = sizeof(data)/sizeof(data[0]), \\
}
#define KEYS(e,n) { KEY(e), KEY(n), }
static struct pubkey keys[] = {
''')
for n in xrange(n + 1):
output.write(' KEYS(e_%d, n_%d),\n' % (n, n))
output.write('};\n')
output.write(u' KEYS(e_{0}, n_{0}),\n'.format(n))
output.write(u'};\n')
pass

def print_gcrypt(output, name, val):
output.write('#include <stdint.h>\n')
while val[0] == '\0':
val = val[1:]
output.write('static const uint8_t %s[%d] = {\n' % (name, len(val)))
# gcrypt expects 8-bit words most-significant-word first
vwords = bitwise_collect(val, 8)
vwords.reverse()

output.write(u'#include <stdint.h>\n')
output.write(u'static const uint8_t %s[%d] = {\n' % (name, len(vwords)))
idx = 0
for v in val:
if not idx:
output.write('\t')
output.write('0x%.2x, ' % ord(v))
idx += 1
if idx == 8:
for vword in vwords:
if not idx:
output.write(u'\t')
output.write(u'0x{:02x}, '.format(vword))
idx += 1
if idx == 8:
idx = 0
output.write('\n')
output.write(u'\n')
if idx:
output.write('\n')
output.write('};\n\n')

output.write(u'\n')
output.write(u'};\n\n')
def print_gcrypt_keys(output, n):
output.write(r'''
struct key_params {
const uint8_t *e, *n;
uint32_t len_e, len_n;
};

#define KEYS(_e, _n) { \
.e = _e, .len_e = sizeof(_e), \
.n = _n, .len_n = sizeof(_n), \
}

static const struct key_params __attribute__ ((unused)) keys[] = {
''')
for n in xrange(n + 1):
output.write(' KEYS(e_%d, n_%d),\n' % (n, n))
output.write('};\n')


output.write(u'''
struct key_params {
const uint8_t *e, *n;
uint32_t len_e, len_n;
};

#define KEYS(_e, _n) { \\
.e = _e, .len_e = sizeof(_e), \\
.n = _n, .len_n = sizeof(_n), \\
}

static const struct key_params __attribute__ ((unused)) keys[] = {
''')

for n in range(n + 1):
output.write(u' KEYS(e_{0}, n_{0}),\n'.format(n))
output.write(u'};\n')


modes = {
'--ssl': (print_ssl, print_ssl_keys),
'--ssl': (print_ssl, print_ssl_keys),
'--gcrypt': (print_gcrypt, print_gcrypt_keys),
}

Expand All @@ -135,21 +139,20 @@ def print_gcrypt_keys(output, n):
mode = None

if not mode in modes:
print 'Usage: %s [%s] input-file... output-file' % (sys.argv[0], '|'.join(modes.keys()))
print('Usage: {} [{}] input-file... output-file'.format(sys.argv[0], '|'.join(modes.keys())))
sys.exit(2)

output = open(outfile, 'w')

# load key
output = io.open(outfile, 'w')
# load key
idx = 0
for f in files:
try:
key = RSA.load_pub_key(f)
except RSA.RSAError:
key = RSA.load_key(f)
key_contents = io.open(f, 'rb').read()
key = RSA.importKey(key_contents)

modes[mode][0](output, 'e_%d' % idx, key.e[4:])
modes[mode][0](output, 'n_%d' % idx, key.n[4:])
idx += 1
modes[mode][0](output, 'e_{}'.format(idx), key.e)
modes[mode][0](output, 'n_{}'.format(idx), key.n)

idx += 1

modes[mode][1](output, idx - 1)