add multiple input/output file formats

* input: credentials, dubp mnemonic, ewif, nacl, pem pksc8, pubsec, seed, ssb, wif
* output: ewif, nacl, pb2, pem pksc8, pubsec, seed, wif
* bump version 0.0.4
This commit is contained in:
Yann Autissier 2022-09-18 22:55:16 +02:00
parent 4556ee4d32
commit 793c96f458
3 changed files with 396 additions and 106 deletions

View File

@ -28,7 +28,7 @@ $ dpgpid show
### keygen
keygen helps you to generate an ed25519 key in different formats
keygen helps you to generate or convert an ed25519 key in different formats.
* Show duniter public key for user "username" and password "password"
@ -42,12 +42,30 @@ $ keygen username password
$ keygen -pk -t ipfs username password
```
* Show duniter public and secret keys for GPG key matching uid "username" and protected with password "password"
* Show duniter public and secret keys for GPG key matching uid "username" and locked with password "password"
```shell
$ keygen -pkg username password
```
* Write secret key to a pem pkcs8 file for user "username" and password "password"
```shell
$ keygen -o /tmp/ipns.pem username password
```
* Write secret key to a wif file for user "username" and password "password"
```shell
$ keygen -f wif -o /tmp/duniter.wif username password
```
* Write base58 public and secret keys to a pubsec file for user "username" and password "password"
```shell
$ keygen -f pubsec -o /tmp/duniter.pubsec username password
```
## Tests
Run tests

266
keygen
View File

@ -27,7 +27,7 @@ import argparse
import base58
import base64
import configparser
import cryptography.hazmat.primitives.asymmetric.ed25519 as ed25519
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives import serialization
import duniterpy.key
import gpg
@ -44,15 +44,15 @@ import sys
import time
import warnings
__version__='0.0.3'
__version__='0.0.4'
class keygen:
def __init__(self):
# desc: generate ed25519 keys suitables for duniter or ipfs
self.parser = argparse.ArgumentParser(description="""
Generate ed25519 keys suitables for duniter or ipfs.
It converts your Duniter username and password or a GPG key to a duniter
pub/sec key or an IPFS PeerID/PrivateKEY.""")
Generate ed25519 keys suitables for duniter and ipfs.
It converts an ed25519 key, duniter username/password, or a GPG key, to
a duniter wallet or an IPFS PeerID/PrivateKEY.""")
self.parser.add_argument(
"-d",
"--debug",
@ -64,20 +64,20 @@ class keygen:
"--format",
dest="format",
default=None,
help="output file format: [pb2|pem|pubsec], default: pem (pkcs8)",
help="output file format: [ewif|nacl|pb2|pem|pubsec|seed|wif], default: pem (pkcs8)",
)
self.parser.add_argument(
"-g",
"--gpg",
action="store_true",
help="use gpg key from user id matched by username option as input",
help="use gpg key with uid matched by username",
)
self.parser.add_argument(
"-i",
"--input",
dest="input",
default=None,
help="read public and secret keys in pubsec format from file INPUT",
help="read ed25519 key from file INPUT, autodetect format: [credentials|ewif|libnacl|mnemonic|pubsec|seedhex|wif]",
)
self.parser.add_argument(
"-k",
@ -86,17 +86,23 @@ class keygen:
help="show public and secret keys",
)
self.parser.add_argument(
"-m",
"--mnemonic",
action="store_true",
help="use username as a DUBP mnemonic passphrase",
)
self.parser.add_argument(
"-o",
"--output",
dest="output",
default=None,
help="write public and secret keys to file OUTPUT",
help="write ed25519 key to file OUTPUT",
)
self.parser.add_argument(
"-p",
"--prefix",
action="store_true",
help="prefix key with key type",
help="prefix output text with key type",
)
self.parser.add_argument(
"-q",
@ -143,22 +149,24 @@ class keygen:
if self.password is None:
if self.username is None:
self.parser.error(f"keygen requires an input file or username args")
if self.format not in [None, 'ewif', 'nacl', 'pb2', 'pem', 'pubsec', 'seed', 'wif']:
self.parser.error(f"format not valid")
def _cleanup(self):
log.debug("keygen._cleanup()")
if hasattr(self, 'armored_pgp_secret_key') and self.armored_pgp_secret_key:
clearmem(self.armored_pgp_secret_key)
log.debug("cleared: keygen.armored_pgp_secret_key")
if hasattr(self, 'duniterpy'):
if hasattr(self.duniterpy, 'seed') and self.duniterpy.seed:
clearmem(self.duniterpy.seed)
log.debug("cleared: keygen.duniterpy.seed")
if hasattr(self.duniterpy, 'sk') and self.duniterpy.sk:
clearmem(self.duniterpy.sk)
log.debug("cleared: keygen.duniterpy.sk")
if hasattr(self, 'ed25519_secret_base58') and self.ed25519_secret_base58:
clearmem(self.ed25519_secret_base58)
log.debug("cleared: keygen.ed25519_secret_base58")
if hasattr(self, 'ed25519_secret_base64') and self.ed25519_secret_base64:
clearmem(self.ed25519_secret_base64)
log.debug("cleared: keygen.ed25519_secret_base64")
if hasattr(self, 'duniter'):
if hasattr(self.duniter, 'sk') and self.duniterpy.sk:
clearmem(self.duniterpy.sk)
log.debug("cleared: keygen.duniterpy.sk")
if hasattr(self, 'ed25519_secret_bytes') and self.ed25519_secret_bytes:
clearmem(self.ed25519_secret_bytes)
log.debug("cleared: keygen.ed25519_secret_bytes")
@ -168,12 +176,18 @@ class keygen:
if hasattr(self, 'ed25519_secret_protobuf2') and self.ed25519_secret_protobuf2:
clearmem(self.ed25519_secret_protobuf2)
log.debug("cleared: keygen.ed25515_secret_protobuf2")
if hasattr(self, 'ed25519_seed_bytes') and self.ed25519_seed_bytes:
clearmem(self.ed25519_seed_bytes)
log.debug("cleared: keygen.ed25519_seed_bytes")
if hasattr(self, 'ipfs_privkey') and self.ipfs_privkey:
clearmem(self.ipfs_privkey)
log.debug("cleared: keygen.ipfs_privkey")
if hasattr(self, 'password') and self.password:
clearmem(self.password)
log.debug("cleared: keygen.password")
if hasattr(self, 'pgp_secret_armored') and self.pgp_secret_armored:
clearmem(self.pgp_secret_armored)
log.debug("cleared: keygen.pgp_secret_armored")
if hasattr(self, 'pgpy'):
if hasattr(self.pgpy._key.keymaterial, 'p') and self.pgpy._key.keymaterial.p and not isinstance(self.pgpy._key.keymaterial.p, pgpy.packet.fields.ECPoint):
clearmem(self.pgpy._key.keymaterial.p)
@ -184,12 +198,9 @@ class keygen:
if hasattr(self.pgpy._key.keymaterial, 's') and self.pgpy._key.keymaterial.s:
clearmem(self.pgpy._key.keymaterial.s)
log.debug("cleared: keygen.pgpy._key.material.s")
if hasattr(self, 'pgp_key_seed') and self.pgp_key_seed:
clearmem(self.pgp_key_seed)
log.debug("cleared: keygen.pgp_key_seed")
if hasattr(self, 'pgp_key_value') and self.pgp_key_value:
clearmem(self.pgp_key_value)
log.debug("cleared: keygen.pgp_key_value")
if hasattr(self, 'username') and self.username:
clearmem(self.username)
log.debug("cleared: keygen.username")
def _invalid_type(self):
log.debug("keygen._invalid_type()")
@ -213,22 +224,43 @@ class keygen:
def _output_file(self):
log.debug("keygen._output_file()")
if self.format == 'pb2':
if self.format == 'ewif':
if not hasattr(self, 'duniterpy'):
self.duniterpy_from_ed25519()
if not self.password:
with pynentry.PynEntry() as p:
p.description = f"""Data in EWIF file needs to be encrypted.
Please enter a password to encrypt seed.
"""
p.prompt = 'Passphrase:'
try:
self.password = p.get_pin()
except pynentry.PinEntryCancelled:
log.warning('Cancelled! Goodbye.')
self._cleanup()
exit(2)
self.duniterpy.save_ewif_file(self.output, self.password)
elif self.format == 'nacl':
if not hasattr(self, 'duniterpy'):
self.duniterpy_from_ed25519()
self.duniterpy.save_private_key(self.output)
elif self.format == 'pb2':
if not hasattr(self, 'ed25519_secret_protobuf2'):
self.protobuf2_from_ed25519()
with open(self.output, "wb") as fh:
fh.write(self.ed25519_secret_protobuf2)
elif self.format == 'pubsec':
if not hasattr(self, 'ed25519_public_base58') or not hasattr(self, 'ed25519_secret_base58'):
self.base58_from_ed25519()
with open(self.output, "w") as fh:
fh.write(
f"""Type: PubSec
Version: 1
pub: {self.ed25519_public_base58}
sec: {self.ed25519_secret_base58}
"""
)
if not hasattr(self, 'duniterpy'):
self.duniterpy_from_ed25519()
self.duniterpy.save_pubsec_file(self.output)
elif self.format == 'seed':
if not hasattr(self, 'duniterpy'):
self.duniterpy_from_ed25519()
self.duniterpy.save_seedhex_file(self.output)
elif self.format == 'wif':
if not hasattr(self, 'duniterpy'):
self.duniterpy_from_ed25519()
self.duniterpy.save_wif_file(self.output)
else:
if not hasattr(self, 'ed25519_secret_pem_pkcs8'):
self.pem_pkcs8_from_ed25519()
@ -316,8 +348,8 @@ sec: {self.ed25519_secret_base58}
self.ipfs_from_protobuf2()
self._output(self.ipfs_peerid, self.ipfs_privkey, 'PeerID: ', 'PrivKEY: ')
def duniterpy_from_salt_and_password(self):
log.debug("keygen.duniterpy_from_salt_and_password()")
def duniterpy_from_credentials(self):
log.debug("keygen.duniterpy_from_credentials()")
scrypt_params = duniterpy.key.scrypt_params.ScryptParams(
int(self.config.get('scrypt', 'n')) if self.config.has_option('scrypt', 'n') else 4096,
int(self.config.get('scrypt', 'r')) if self.config.has_option('scrypt', 'r') else 16,
@ -339,17 +371,107 @@ sec: {self.ed25519_secret_base58}
self.password,
scrypt_params
)
log.debug("keygen.duniterpy.seed: %s" % self.duniterpy.seed)
def duniterpy_from_ed25519(self):
log.debug("keygen.duniterpy_from_ed25519()")
self.duniterpy = duniterpy.key.SigningKey(self.ed25519_secret_bytes[:32])
log.debug("keygen.duniterpy.seed: %s" % self.duniterpy.seed)
def duniterpy_from_file(self):
log.debug("keygen.duniterpy_from_file()")
try:
with open(self.input, 'r') as file:
lines = file.readlines()
if len(lines) > 0:
line = lines[0].strip()
regex_ewif = re.compile('^Type: EWIF$')
regex_nacl = re.compile('^\\s*{\\s*"priv":\\s*"[0-9a-fA-F]+",\\s*"verify":\\s*"[0-9a-fA-F]+",\\s*"sign":\\s*"[0-9a-fA-F]+"\\s*}$')
regex_pem = re.compile('^-----BEGIN PRIVATE KEY-----$')
regex_pubsec = re.compile('^Type: PubSec$')
regex_seed = re.compile('^[0-9a-fA-F]{64}$')
regex_ssb = re.compile('\\s*{\\s*"curve": "ed25519",\\s*"public": "(.+)\\.ed25519",\\s*"private":\\s*"(.+)\\.ed25519",\\s*"id":\\s*"@(.+).ed25519"\\s*}')
regex_wif = re.compile('^Type: WIF$')
if re.search(regex_ewif, line):
log.info("input file format detected: ewif")
if not self.password:
with pynentry.PynEntry() as p:
p.description = f"""Data in EWIF file needs to be decrypted.
Please enter a password to decrypt seed.
"""
p.prompt = 'Passphrase:'
try:
self.password = p.get_pin()
except pynentry.PinEntryCancelled:
log.warning('Cancelled! Goodbye.')
self._cleanup()
exit(2)
self.duniterpy = duniterpy.key.SigningKey.from_ewif_file(self.input, self.password)
elif re.search(regex_nacl, line):
log.info("input file format detected: nacl")
self.duniterpy = duniterpy.key.SigningKey.from_private_key(self.input)
elif re.search(regex_pem, line):
log.info("input file format detected: pem")
self.ed25519_secret_bytes = serialization.load_pem_private_key(''.join(lines).encode(), password=None).private_bytes(encoding=serialization.Encoding.Raw, format=serialization.PrivateFormat.Raw, encryption_algorithm=serialization.NoEncryption())
self.duniterpy_from_ed25519()
## at this stage, self.ed25519_secret_bytes contains only the 32 seed bytes and not the 32 seed bytes + 32 public bytes as it should
# we need to call self.ed25519_from_duniterpy() later to correctly build the self.ed25519_secret_bytes
elif re.search(regex_pubsec, line):
log.info("input file format detected: pubsec")
self.duniterpy = duniterpy.key.SigningKey.from_pubsec_file(self.input)
elif re.search(regex_seed, line):
log.info("input file format detected: seed")
self.duniterpy = duniterpy.key.SigningKey.from_seedhex_file(self.input)
elif re.search(regex_ssb, line):
log.info("input file format detected: ssb")
self.duniterpy = duniterpy.key.SigningKey.from_ssb_file(self.input)
elif re.search(regex_wif, line):
log.info("input file format detected: wif")
self.duniterpy = duniterpy.key.SigningKey.from_wif_file(self.input)
elif len(line.split(' ')) == 12:
log.info("input file format detected: mnemonic")
self.username = line
self.duniterpy_from_mnemonic()
elif len(lines) > 1:
log.info("input file format detected: credentials")
self.username = line
self.password = lines[1].strip()
self.duniterpy_from_credentials()
else:
raise NotImplementedError(f"""unable to detect input file format.""")
except Exception as e:
log.error(f"""Unable to open file {self.input}: {e}""")
self._cleanup()
exit(1)
log.debug("keygen.duniterpy.seed: %s" % self.duniterpy.seed)
def duniterpy_from_mnemonic(self):
log.debug("keygen.duniterpy_from_mnemonic()")
scrypt_params = duniterpy.key.scrypt_params.ScryptParams(
int(self.config.get('scrypt', 'n')) if self.config.has_option('scrypt', 'n') else 4096,
int(self.config.get('scrypt', 'r')) if self.config.has_option('scrypt', 'r') else 16,
int(self.config.get('scrypt', 'p')) if self.config.has_option('scrypt', 'p') else 1,
int(self.config.get('scrypt', 'sl')) if self.config.has_option('scrypt', 'sl') else 32,
)
self.duniterpy = duniterpy.key.SigningKey.from_dubp_mnemonic(
self.username,
scrypt_params
)
log.debug("keygen.duniterpy.seed: %s" % self.duniterpy.seed)
def ed25519(self, args):
log.debug("keygen.ed25519(%s)" % args)
if args.gpg is True:
if args.gpg:
self.ed25519_from_gpg()
elif self.input is None:
self.duniterpy_from_salt_and_password()
self.ed25519_from_duniterpy()
else:
self.base58_from_pubsec()
self.ed25519_from_base58()
if self.input:
self.duniterpy_from_file()
else:
if self.mnemonic:
self.duniterpy_from_mnemonic()
else:
self.duniterpy_from_credentials()
self.ed25519_from_duniterpy()
def ed25519_from_base58(self):
log.debug("keygen.ed25519_from_base58()")
@ -387,13 +509,11 @@ sec: {self.ed25519_secret_base58}
log.debug("keygen.gpg_seckey.uids=%s" % self.gpg_seckey.uids)
log.debug("keygen.gpg_seckey.owner_trust=%s" % self.gpg_seckey.owner_trust)
log.debug("keygen.gpg_seckey.last_update=%s" % self.gpg_seckey.last_update)
self.armored_pgp_public_key = self.gpg.key_export(self.gpg_seckey.fpr)
log.debug("keygen.armored_pgp_public_key=%s" % self.armored_pgp_public_key)
if self.password:
self.gpg.set_pinentry_mode(gpg.constants.PINENTRY_MODE_LOOPBACK)
self.armored_pgp_secret_key = self.gpg.key_export_secret(self.gpg_seckey.fpr)
log.debug("keygen.armored_pgp_secret_key=%s" % self.armored_pgp_secret_key)
if not self.armored_pgp_secret_key:
self.pgp_secret_armored = self.gpg.key_export_secret(self.gpg_seckey.fpr)
log.debug("keygen.pgp_secret_armored=%s" % self.pgp_secret_armored)
if not self.pgp_secret_armored:
log.error(f"""Unable to export gpg secret key id "{self.gpg_seckey.fpr}" of user "{self.username}". Please check your password!""")
self._cleanup()
exit(2)
@ -401,7 +521,7 @@ sec: {self.ed25519_secret_base58}
# remove CryptographyDeprecationWarning about deprecated
# SymmetricKeyAlgorithm IDEA, CAST5 and Blowfish (PGPy v0.5.4)
warnings.simplefilter('ignore')
self.pgpy, _ = pgpy.PGPKey.from_blob(self.armored_pgp_secret_key)
self.pgpy, _ = pgpy.PGPKey.from_blob(self.pgp_secret_armored)
def ed25519_from_pgpy(self):
log.debug("keygen.ed25519_from_pgpy()")
@ -428,17 +548,35 @@ sec: {self.ed25519_secret_base58}
with self.pgpy.unlock(self.password):
assert self.pgpy.is_unlocked
log.debug("keygen.pgpy.is_unlocked=%s" % self.pgpy.is_unlocked)
self.pgp_key_seed_from_pgpy()
self.ed25519_seed_bytes_from_pgpy()
except Exception as e:
log.error(f"""Unable to unlock pgp secret key id "{self.pgpy.fingerprint.keyid}" of user "{self.username}". Please check your password!""")
self._cleanup()
exit(2)
else:
self.pgp_key_seed_from_pgpy()
self.ed25519_public_bytes, self.ed25519_secret_bytes = nacl.bindings.crypto_sign_seed_keypair(self.pgp_key_seed)
self.ed25519_seed_bytes_from_pgpy()
self.ed25519_public_bytes, self.ed25519_secret_bytes = nacl.bindings.crypto_sign_seed_keypair(self.ed25519_seed_bytes)
log.debug("keygen.ed25519_public_bytes=%s" % self.ed25519_public_bytes)
log.debug("keygen.ed25519_secret_bytes=%s" % self.ed25519_secret_bytes)
def ed25519_seed_bytes_from_pgpy(self):
log.debug("keygen.ed25519_seed_bytes_from_pgpy()")
self.pgpy_key_type()
if self.pgpy_key_type == 'RSA':
log.debug("keygen.pgpy._key.keymaterial.p=%s" % self.pgpy._key.keymaterial.p)
log.debug("keygen.pgpy._key.keymaterial.q=%s" % self.pgpy._key.keymaterial.q)
# custom seed: use sha256 hash of (p + q)
self.ed25519_seed_bytes = nacl.bindings.crypto_hash_sha256(long_to_bytes(self.pgpy._key.keymaterial.p + self.pgpy._key.keymaterial.q))
p = long_to_bytes(self.pgpy._key.keymaterial.p)
q = long_to_bytes(self.pgpy._key.keymaterial.q)
log.debug("keygen.ed25519_seed_bytes=%s" % self.ed25519_seed_bytes)
elif self.pgpy_key_type in ('ECDSA', 'EdDSA', 'ECDH'):
log.debug("keygen.pgpy._key.keymaterial.s=%s" % self.pgpy._key.keymaterial.s)
self.ed25519_seed_bytes = long_to_bytes(self.pgpy._key.keymaterial.s)
log.debug("keygen.ed25519_seed_bytes=%s" % self.ed25519_seed_bytes)
else:
raise NotImplementedError(f"Getting seed from {self.pgpy_key_type} key is not implemented")
def gpg_passphrase_cb(self, uid_hint, passphrase_info, prev_was_bad):
log.debug("keygen.gpg_passphrase_cb(%s, %s, %s)" % (uid_hint, passphrase_info, prev_was_bad))
return self.password
@ -460,32 +598,6 @@ sec: {self.ed25519_secret_base58}
self.ed25519_secret_pem_pkcs8 = ed25519.Ed25519PrivateKey.from_private_bytes(self.ed25519_secret_bytes[:32]).private_bytes(encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption()).decode('ascii')
log.debug("keygen.ed25519_secret_pem_pkcs8=%s" % self.ed25519_secret_pem_pkcs8)
def pgp_key_seed_from_pgpy(self):
log.debug("keygen.pgp_key_seed_from_pgpy()")
self.pgpy_key_type()
if self.pgpy_key_type == 'RSA':
log.debug("keygen.pgpy._key.keymaterial.p=%s" % self.pgpy._key.keymaterial.p)
log.debug("keygen.pgpy._key.keymaterial.q=%s" % self.pgpy._key.keymaterial.q)
# custom seed: use sha256 hash of (p + q)
self.pgp_key_seed = nacl.bindings.crypto_hash_sha256(long_to_bytes(self.pgpy._key.keymaterial.p + self.pgpy._key.keymaterial.q))
p = long_to_bytes(self.pgpy._key.keymaterial.p)
q = long_to_bytes(self.pgpy._key.keymaterial.q)
self.pgp_key_value = "".join([f"{c:02x}" for c in p]) + "".join([f"{c:02x}" for c in q])
self.pgp_key_size = (len(p) + len(q)) * 8
log.debug("keygen.pgp_key_seed=%s" % self.pgp_key_seed)
log.debug("keygen.pgp_key_value=%s" % self.pgp_key_value)
log.debug("keygen.pgp_key_size=%s" % self.pgp_key_size)
elif self.pgpy_key_type in ('ECDSA', 'EdDSA', 'ECDH'):
log.debug("keygen.pgpy._key.keymaterial.s=%s" % self.pgpy._key.keymaterial.s)
self.pgp_key_seed = long_to_bytes(self.pgpy._key.keymaterial.s)
self.pgp_key_value = "".join([f"{c:02x}" for c in self.pgp_key_seed])
self.pgp_key_size = len(self.pgp_key_seed)*8
log.debug("keygen.pgp_key_seed=%s" % self.pgp_key_seed)
log.debug("keygen.pgp_key_value=%s" % self.pgp_key_value)
log.debug("keygen.pgp_key_size=%s" % self.pgp_key_size)
else:
raise NotImplementedError(f"Getting seed from {self.pgpy_key_type} key is not implemented")
def pgpy_key_type(self):
log.debug("keygen.pgpy_key_type()")
if isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.RSAPriv):

View File

@ -1,9 +1,16 @@
#shellcheck shell=sh
set -eu
PB2_FILE="${SHELLSPEC_TMPBASE}/key.pb2"
PEM_FILE="${SHELLSPEC_TMPBASE}/key.pem"
PUBSEC_FILE="${SHELLSPEC_TMPBASE}/key.pubsec"
CRED_FILE="${SHELLSPEC_TMPBASE}/credentials"
DUBP_FILE="${SHELLSPEC_TMPBASE}/mnemonic"
EWIF_FILE="${SHELLSPEC_TMPBASE}/ed25519.ewif"
NACL_FILE="${SHELLSPEC_TMPBASE}/ed25519.nacl"
PB2_FILE="${SHELLSPEC_TMPBASE}/ed25519.pb2"
PEM_FILE="${SHELLSPEC_TMPBASE}/ed25519.pem"
PUBSEC_FILE="${SHELLSPEC_TMPBASE}/ed25519.pubsec"
SEED_FILE="${SHELLSPEC_TMPBASE}/ed25519.seed"
SSB_FILE="${SHELLSPEC_TMPBASE}/ed25519.ssb"
WIF_FILE="${SHELLSPEC_TMPBASE}/ed25519.wif"
gpg() {
GNUPGHOME="${SHELLSPEC_TMPBASE}" command gpg "$@"
@ -50,13 +57,13 @@ Describe 'keygen'
Describe '--version:'
It 'prints version'
When run keygen --version
The output should include 'v0.0.3'
The output should include 'v0.0.4'
The status should be success
The stderr should equal ""
End
End
Describe 'username password:'
It 'prints base58 public key for user "username" with password "password"'
It 'prints base58 public key for user "username" and password "password"'
When run keygen username password
The output should include '4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The status should be success
@ -64,7 +71,7 @@ Describe 'keygen'
End
End
Describe '-p username password:'
It 'prints prefixed base58 public key for user "username" with password "password"'
It 'prints prefixed base58 public key for user "username" and password "password"'
When run keygen -p username password
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The status should be success
@ -72,7 +79,7 @@ Describe 'keygen'
End
End
Describe '-s username password:'
It 'prints base58 secret key for user "username" with password "password"'
It 'prints base58 secret key for user "username" and password "password"'
When run keygen -s username password
The output should include 'K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
@ -80,7 +87,7 @@ Describe 'keygen'
End
End
Describe '-ps username password:'
It 'prints prefixed base58 secret key for user "username" with password "password"'
It 'prints prefixed base58 secret key for user "username" and password "password"'
When run keygen -ps username password
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
@ -88,7 +95,7 @@ Describe 'keygen'
End
End
Describe '-k username password:'
It 'prints base58 public and secret keys for user "username" with password "password"'
It 'prints base58 public and secret keys for user "username" and password "password"'
When run keygen -k username password
The output should include '4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
@ -97,7 +104,7 @@ Describe 'keygen'
End
End
Describe '-pk username password:'
It 'prints prefixed base58 public and secret keys for user "username" with password "password"'
It 'prints prefixed base58 public and secret keys for user "username" and password "password"'
When run keygen -pk username password
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
@ -106,7 +113,7 @@ Describe 'keygen'
End
End
Describe '-t base58 -pk username password:'
It 'prints prefixed base58 public and secret keys for user "username" with password "password"'
It 'prints prefixed base58 public and secret keys for user "username" and password "password"'
When run keygen -t base58 -pk username password
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
@ -115,7 +122,7 @@ Describe 'keygen'
End
End
Describe '-t base64 -pk username password:'
It 'prints prefixed base64 public and secret keys for user "username" with password "password"'
It 'prints prefixed base64 public and secret keys for user "username" and password "password"'
When run keygen -t base64 -pk username password
The output should include 'pub: NJoTbvcP+m51+XwxrmWqHaOpI1ZD0USwLjqAmV8Boas='
The output should include 'sec: D5eoJaNGoKM172hTdADv3psQf5P6vGDI9D8SRe8TYy80mhNu9w/6bnX5fDGuZaodo6kjVkPRRLAuOoCZXwGhqw=='
@ -124,7 +131,7 @@ Describe 'keygen'
End
End
Describe '-t duniter -pk username password:'
It 'prints prefixed duniter public and secret keys for user "username" with password "password"'
It 'prints prefixed duniter public and secret keys for user "username" and password "password"'
When run keygen -t duniter -pk username password
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
@ -133,7 +140,7 @@ Describe 'keygen'
End
End
Describe '-t ipfs -pk username password:'
It 'prints prefixed ipfs public and secret keys for user "username" with password "password"'
It 'prints prefixed ipfs public and secret keys for user "username" and password "password"'
When run keygen -t ipfs -pk username password
The output should include 'PeerID: 12D3KooWDMhdm5yrvtrbkshXFjkqLedHieUnPioczy9wzdnzquHC'
The output should include 'PrivKEY: CAESQA+XqCWjRqCjNe9oU3QA796bEH+T+rxgyPQ/EkXvE2MvNJoTbvcP+m51+XwxrmWqHaOpI1ZD0USwLjqAmV8Boas='
@ -141,9 +148,82 @@ Describe 'keygen'
The stderr should equal ""
End
End
Describe '-pkm "tongue cute mail ...":'
It 'prints prefixed base58 public and secret keys for mnemonic "tongue cute mail ..."'
When run keygen -pkm "tongue cute mail fossil great frozen same social weasel impact brush kind"
The output should include 'pub: 732SSfuwjB7jkt9th1zerGhphs6nknaCBCTozxUcPWPU'
The output should include 'sec: 4NHNg9KSp81nXAN4Gmwx4EZ9bCdahnJ9jozJa1cGj9oDvzx9kCtNSvasqTZVm6VJXBQxyakZ5uZnj8AS6g87kK3x'
The status should be success
The stderr should equal ""
End
End
Describe "-pki ${CRED_FILE}"
printf 'username\npassword\n' > "${CRED_FILE}"
It 'prints prefixed base58 public and secret keys for username and password read from credentials file"'
When run keygen -pki "${CRED_FILE}" -v
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should include 'input file format detected: credentials'
End
rm -f "${CRED_FILE}"
End
Describe "-pki ${DUBP_FILE}"
printf 'tongue cute mail fossil great frozen same social weasel impact brush kind\n' > "${DUBP_FILE}"
It 'prints prefixed base58 public and secret keys for mnemonic read from dubp file"'
When run keygen -pki "${DUBP_FILE}" -v
The output should include 'pub: 732SSfuwjB7jkt9th1zerGhphs6nknaCBCTozxUcPWPU'
The output should include 'sec: 4NHNg9KSp81nXAN4Gmwx4EZ9bCdahnJ9jozJa1cGj9oDvzx9kCtNSvasqTZVm6VJXBQxyakZ5uZnj8AS6g87kK3x'
The status should be success
The stderr should include 'input file format detected: mnemonic'
End
rm -f "${DUBP_FILE}"
End
Describe "-f nacl -o ${NACL_FILE} username password:"
rm -f "${NACL_FILE}"
It 'writes secret key to a libnacl file for user "username" and password "password"'
When run keygen -f nacl -o "${NACL_FILE}" username password
The path "${NACL_FILE}" should exist
The contents of file "${NACL_FILE}" should include '{"priv": "0f97a825a346a0a335ef68537400efde9b107f93fabc60c8f43f1245ef13632f349a136ef70ffa6e75f97c31ae65aa1da3a9235643d144b02e3a80995f01a1ab", "verify": "349a136ef70ffa6e75f97c31ae65aa1da3a9235643d144b02e3a80995f01a1ab", "sign": "0f97a825a346a0a335ef68537400efde9b107f93fabc60c8f43f1245ef13632f"}'
The status should be success
The stderr should equal ""
End
End
Describe "-pki ${NACL_FILE}:"
It 'prints prefixed base58 public and secret keys for ed25519 key read from libnacl file"'
When run keygen -pki "${NACL_FILE}" -v
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should include 'input file format detected: nacl'
End
rm -f "${NACL_FILE}"
End
Describe "-f ewif -o ${EWIF_FILE} username password:"
rm -f "${EWIF_FILE}"
It 'writes encrypted secret key to a ewif file for user "username" and password "password"'
When run keygen -f ewif -o "${EWIF_FILE}" username password
The path "${EWIF_FILE}" should exist
The contents of file "${EWIF_FILE}" should include 'Type: EWIF'
The contents of file "${EWIF_FILE}" should include 'Version: 1'
The contents of file "${EWIF_FILE}" should include 'Data: 2w6iPHHjrfGT3HWvNV1cw3ZpGXAAQtfYzRxDXUkyW2y5WBorLtDUY'
The status should be success
The stderr should equal ""
End
End
Describe "-pki ${EWIF_FILE}:"
It 'prints prefixed base58 public and secret keys for ed25519 key read from EWIF file"'
When run keygen -pki "${EWIF_FILE}" -v username password
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should include 'input file format detected: ewif'
End
rm -f "${EWIF_FILE}"
End
Describe "-o ${PEM_FILE} username password:"
rm -f "${PEM_FILE}"
It 'writes pkcs8 secret key to a pem file for user "username" with password "password"'
It 'writes pkcs8 secret key to a pem file for user "username" and password "password"'
When run keygen -o "${PEM_FILE}" -t ipfs username password
The path "${PEM_FILE}" should exist
The contents of file "${PEM_FILE}" should include '-----BEGIN PRIVATE KEY-----'
@ -155,7 +235,7 @@ Describe 'keygen'
End
Describe "-f pem -o ${PEM_FILE} username password:"
rm -f "${PEM_FILE}"
It 'writes pkcs8 secret key to a pem file for user "username" with password "password"'
It 'writes pkcs8 secret key to a pem file for user "username" and password "password"'
When run keygen -f pem -o "${PEM_FILE}" -t ipfs username password
The path "${PEM_FILE}" should exist
The contents of file "${PEM_FILE}" should include '-----BEGIN PRIVATE KEY-----'
@ -165,9 +245,19 @@ Describe 'keygen'
The stderr should equal ""
End
End
Describe "-pki ${PEM_FILE}:"
It 'prints prefixed base58 public and secret keys for ed25519 key read from pkcs8 pem file"'
When run keygen -pki "${PEM_FILE}" -v
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should include 'input file format detected: pem'
End
rm -f "${PEM_FILE}"
End
Describe "-f pb2 -o ${PB2_FILE} username password:"
rm -f "${PB2_FILE}"
It 'writes protobuf2 secret key to a pb2 file for user "username" with password "password"'
It 'writes protobuf2 secret key to a pb2 file for user "username" and password "password"'
decode_pb2() {
xxd -ps "${PB2_FILE}"
}
@ -183,10 +273,11 @@ Describe 'keygen'
The status should be success
The stderr should equal ""
End
rm -f "${PB2_FILE}"
End
Describe "-f pubsec -o ${PUBSEC_FILE} username password:"
rm -f "${PUBSEC_FILE}"
It 'writes base58 public and secret keys to a pubsec file for user "username" with password "password"'
It 'writes base58 public and secret keys to a pubsec file for user "username" and password "password"'
When run keygen -f pubsec -o "${PUBSEC_FILE}" username password
The path "${PUBSEC_FILE}" should exist
The contents of file "${PUBSEC_FILE}" should include 'Type: PubSec'
@ -199,7 +290,7 @@ Describe 'keygen'
End
Describe "-o ${PUBSEC_FILE} -t duniter username password:"
rm -f "${PUBSEC_FILE}"
It 'writes duniter public and secret keys to a pubsec file for user "username" with password "password"'
It 'writes duniter public and secret keys to a pubsec file for user "username" and password "password"'
When run keygen -o "${PUBSEC_FILE}" -t duniter username password
The path "${PUBSEC_FILE}" should exist
The contents of file "${PUBSEC_FILE}" should include 'Type: PubSec'
@ -210,17 +301,71 @@ Describe 'keygen'
The stderr should equal ""
End
End
Describe "-i ${PUBSEC_FILE} -t ipfs -pk:"
Describe "-pki ${PUBSEC_FILE} -t ipfs:"
It 'prints prefixed ipfs public and secret keys for base58 keys read in a pubsec file'
When run keygen -i "${PUBSEC_FILE}" -t ipfs -pk
When run keygen -pki "${PUBSEC_FILE}" -t ipfs -v
The output should include 'PeerID: 12D3KooWDMhdm5yrvtrbkshXFjkqLedHieUnPioczy9wzdnzquHC'
The output should include 'PrivKEY: CAESQA+XqCWjRqCjNe9oU3QA796bEH+T+rxgyPQ/EkXvE2MvNJoTbvcP+m51+XwxrmWqHaOpI1ZD0USwLjqAmV8Boas='
The status should be success
The stderr should include 'input file format detected: pubsec'
End
rm -f "${PUBSEC_FILE}"
End
Describe "-pki ${SSB_FILE}:"
printf '{ "curve": "ed25519", "public": "cFVodZoKwLcmXbM6UeASdl8+7+Uo8PNOuFnlcqk7qUc=.ed25519", "private": "lUqlXYxjkM0/ljtGnwoM0CfP6ORA2DKZnzsQ4dJ1tKJwVWh1mgrAtyZdszpR4BJ2Xz7v5Sjw8064WeVyqTupRw==.ed25519", "id": "@cFVodZoKwLcmXbM6UeASdl8+7+Uo8PNOuFnlcqk7qUc=.ed25519" }\n' > "${SSB_FILE}"
It 'prints prefixed base58 public and secret keys for ed25519 key read from ssb file"'
When run keygen -pki "${SSB_FILE}" -v
The output should include 'pub: 8ZWCTFBUczYRucyvTgJL6oefj28u243LYU4ZjYKn4XDG'
The output should include 'sec: 3z7vcMHQhnVPTEEaFQ5gxn2NHkmJsFHkZ4W2aoAvt3Jt5ZYhFV1M6NEkm7Lr75pEF61oSkQVsaih9cQWBP2JmbVQ'
The status should be success
The stderr should include 'input file format detected: ssb'
End
rm -f "${SSB_FILE}"
End
Describe "-f seed -o ${SEED_FILE} username password:"
rm -f "${SEED_FILE}"
It 'writes encoded secret key to a wif file for user "username" and password "password"'
When run keygen -f seed -o "${SEED_FILE}" username password
The path "${SEED_FILE}" should exist
The contents of file "${SEED_FILE}" should include '0f97a825a346a0a335ef68537400efde9b107f93fabc60c8f43f1245ef13632f'
The status should be success
The stderr should equal ""
End
End
Describe "-pki ${SEED_FILE}:"
It 'prints prefixed base58 public and secret keys for ed25519 key read from seed file"'
When run keygen -pki "${SEED_FILE}" -v
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should include 'input file format detected: seed'
End
rm -f "${SEED_FILE}"
End
Describe "-f wif -o ${WIF_FILE} username password:"
rm -f "${WIF_FILE}"
It 'writes encoded secret key to a wif file for user "username" and password "password"'
When run keygen -f wif -o "${WIF_FILE}" username password
The path "${WIF_FILE}" should exist
The contents of file "${WIF_FILE}" should include 'Type: WIF'
The contents of file "${WIF_FILE}" should include 'Version: 1'
The contents of file "${WIF_FILE}" should include 'Data: 7972e1McMMURp9R1MDCH1UMEEnF2bKAjc2WtEW3JyAVwMVT'
The status should be success
The stderr should equal ""
End
End
Describe "-pki ${WIF_FILE}:"
It 'prints prefixed base58 public and secret keys for ed25519 key read from WIF file"'
When run keygen -pki "${WIF_FILE}" -v
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should include 'input file format detected: wif'
End
rm -f "${WIF_FILE}"
End
Describe '-t gpg username password birthday:'
It 'creates a password protected gpg key for user username'
It 'creates a password protected gpg key for user "username"'
Skip "You should implement it !"
When run keygen -t pgp username password birthday
The status should be success
@ -228,7 +373,7 @@ Describe 'keygen'
End
Describe '-pkg username:'
gpg --batch --import --quiet specs/username.asc
It 'prints prefixed base58 public and secret keys for ed25519 gpg key matching "username"'
It 'prints prefixed base58 public and secret keys for ed25519 gpg key matching uid "username"'
When run keygen -pkg username
The output should include 'pub: 2g5UL2zhkn5i7oNYDpWo3fBuWvRYVU1AbMtdVmnGzPNv'
The output should include 'sec: 5WtYFfA26nTfG496gAKhkrLYUMMnwXexmE1E8Q7PvtQEyscHfirsdMzW34zDp7WEkt3exNEVwoG4ajZYrm62wpi2'
@ -239,7 +384,7 @@ Describe 'keygen'
End
Describe '-pkg username@protected password:'
gpg --batch --import --quiet specs/username_protected.asc
It 'prints prefixed public and secret keys for ed25519 gpg key matching "username@protected" locked with "password"'
It 'prints prefixed public and secret keys for ed25519 gpg key matching uid "username@protected" and locked with password "password"'
When run keygen -pkg username@protected password
The output should include 'pub: C1cRu7yb5rZhsmRHQkeZxusAhtYYJypcnXpY3HycEKsU'
The output should include 'sec: VWaEdDroSCoagJDsBnDNUtXJtKAJYdqL6XKNiomz8DtiyF44FvpiMmhidXt2j8HhDBKPZ67xBGcZPnj4Myk6cB8'
@ -250,7 +395,7 @@ Describe 'keygen'
End
Describe '-pkg usersame:'
gpg --batch --import --quiet specs/usersame.asc
It 'prints prefixed base58 public and secret keys for rsa gpg key matching "usersame"'
It 'prints prefixed base58 public and secret keys for rsa gpg key matching uid "usersame"'
When run keygen -pkg usersame
The output should include 'pub: 4NxSjjys6bo8mhM919MkvNkNPFu4zpFyxu1r7yJ39K87'
The output should include 'sec: 2cLFNeXiqcKKv5BF9JVTwtWmFHLvjDkJkrCyQbST9oYbsQLHsVaUAzbwrv5YfzQcPHu6e6XUzdstKy4kLhgDSGiw'
@ -261,7 +406,7 @@ Describe 'keygen'
End
Describe '-pkg usersame@protected password:'
gpg --batch --import --quiet specs/usersame_protected.asc
It 'prints prefixed public and secret keys for rsa gpg key matching "usersame@protected" locked with "password"'
It 'prints prefixed public and secret keys for rsa gpg key matching uid "usersame@protected" and locked with password "password"'
When run keygen -pkg usersame@protected password
The output should include 'pub: 5kh2uqNTuYsLN7fwSRP3JWM4Hotcpdkb7frRNZwo9BPp'
The output should include 'sec: LdWjjkP7gRzH4k4gNkQs2er26bE2Dhz7cGPE8fMNixe1Uv2ZHbo1QtyZxmDeTP77y6HVLbHNoXdMTHdo6ip9PHk'
@ -270,4 +415,19 @@ Describe 'keygen'
End
gpg --batch --delete-secret-and-public-key --yes 78BC5CD37664E5C1AA85AC97ABC22BF0C070C9AD
End
Describe "-g -o ${PUBSEC_FILE} -t duniter username:"
rm -f "${PUBSEC_FILE}"
gpg --batch --import --quiet specs/username.asc
It 'writes duniter public and secret keys to a pubsec file for gpg key matching uid "username"'
When run keygen -g -o "${PUBSEC_FILE}" -t duniter username
The path "${PUBSEC_FILE}" should exist
The contents of file "${PUBSEC_FILE}" should include 'Type: PubSec'
The contents of file "${PUBSEC_FILE}" should include 'Version: 1'
The contents of file "${PUBSEC_FILE}" should include 'pub: 2g5UL2zhkn5i7oNYDpWo3fBuWvRYVU1AbMtdVmnGzPNv'
The contents of file "${PUBSEC_FILE}" should include 'sec: 5WtYFfA26nTfG496gAKhkrLYUMMnwXexmE1E8Q7PvtQEyscHfirsdMzW34zDp7WEkt3exNEVwoG4ajZYrm62wpi2'
The status should be success
The stderr should equal ""
End
gpg --batch --delete-secret-and-public-key --yes 4D1CDB77E91FFCD81B10F9A7079E5BF4721944FB
End
End