Compare commits

...

2 Commits

Author SHA1 Message Date
Yann Autissier 2a0ddd43af rename gpgkey to keygen
* add support for ipfs key import format
2022-06-25 22:43:28 +02:00
Yann Autissier 92ae485077 RSA custom seed 2022-05-29 21:51:44 +02:00
4 changed files with 286 additions and 266 deletions

View File

@ -48,14 +48,14 @@ RUN apk add --no-cache \
|tar --strip-components 1 -C /opt/shellspec -xzf - \ |tar --strip-components 1 -C /opt/shellspec -xzf - \
&& ln -s /opt/shellspec/shellspec ./bin/shellspec && ln -s /opt/shellspec/shellspec ./bin/shellspec
COPY --from=ipfs/go-ipfs:v0.13.0-rc1 /usr/local/bin/ipfs ./bin/ COPY --from=ipfs/go-ipfs:v0.13.0 /usr/local/bin/ipfs ./bin/
COPY README.md ./ COPY README.md ./
COPY COPYING ./ COPY COPYING ./
COPY Makefile ./ COPY Makefile ./
COPY .shellspec ./ COPY .shellspec ./
COPY specs/ ./specs/ COPY specs/ ./specs/
COPY dpgpid ./bin/dpgpid COPY dpgpid ./bin/dpgpid
COPY gpgkey ./bin/gpgkey COPY keygen ./bin/keygen
ENV PATH=/opt/dpgpid/bin:$PATH ENV PATH=/opt/dpgpid/bin:$PATH

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# link: https://git.p2p.legal/aya/dpgpid/ # link: https://git.p2p.legal/aya/dpgpid/
# desc: gpgkey converts ed25519 gpg keys to ed25519 duniter and ipfs keys # desc: generate ed25519 keys suitable for duniter or ipfs
# Copyleft 2022 Yann Autissier <aya@asycn.io> # Copyleft 2022 Yann Autissier <aya@asycn.io>
# all crypto science belongs to Pascal Engélibert <tuxmain@zettascript.org> # all crypto science belongs to Pascal Engélibert <tuxmain@zettascript.org>
@ -33,6 +33,7 @@ from cryptography.hazmat.primitives import serialization
import duniterpy.key import duniterpy.key
import gpg import gpg
import nacl.bindings import nacl.bindings
import nacl.encoding
import pgpy import pgpy
import logging as log import logging as log
import os import os
@ -43,7 +44,7 @@ import time
__version__='0.0.1' __version__='0.0.1'
class gpgkey: class keygen:
def __init__(self): def __init__(self):
self.parser = argparse.ArgumentParser() self.parser = argparse.ArgumentParser()
self.parser.add_argument( self.parser.add_argument(
@ -57,7 +58,20 @@ class gpgkey:
"--input", "--input",
dest="input", dest="input",
default=None, default=None,
help="read credentials from file INPUT", help="read public and secret keys in pubsec format from file INPUT",
)
self.parser.add_argument(
"-g",
"--gpg",
action="store_true",
help="use gpg key from user id matched by username option as input",
)
self.parser.add_argument(
"-o",
"--output",
dest="output",
default=None,
help="write public and secret keys to file OUTPUT",
) )
self.parser.add_argument( self.parser.add_argument(
"-q", "-q",
@ -66,11 +80,11 @@ class gpgkey:
help="show only errors", help="show only errors",
) )
self.parser.add_argument( self.parser.add_argument(
"-o", "-t",
"--output", "--type",
dest="output", dest="type",
default=None, default="ipfs",
help="write keys to file OUTPUT", help="output key type : [ duniter | ipfs ]",
) )
self.parser.add_argument( self.parser.add_argument(
"-v", "-v",
@ -84,11 +98,7 @@ class gpgkey:
help="show version and exit", help="show version and exit",
) )
self.parser.add_argument( self.parser.add_argument(
'command', 'username',
help="duniter|ipfs",
nargs="?",
)
self.parser.add_argument( 'username',
nargs="?", nargs="?",
) )
self.parser.add_argument( self.parser.add_argument(
@ -96,38 +106,43 @@ class gpgkey:
nargs="?", nargs="?",
) )
def _check_args(self): def _check_args(self, args):
log.debug("def gpgkey._check_args(self)") log.debug("def keygen._check_args(self, args)")
log.debug("self.command=%s" % self.command)
log.debug("self.username=%s" % self.username) log.debug("self.username=%s" % self.username)
log.debug("self.password=%s" % self.password) log.debug("self.password=%s" % self.password)
if self.command: if self.input is None:
if self.input is None: if self.password is None:
if self.password is None or self.username is None: if self.username is None or args.gpg is False:
self.parser.error(f"{self.command} requires an input file or username and password args") self.parser.error(f"keygen requires an input file or username and password args")
def _invalid_command(self): def _invalid_type(self):
log.debug("def gpgkey._invalid_command(self)") log.debug("def keygen._invalid_type(self)")
self.parser.error(f"{self.command} is not a valid command.") self.parser.error(f"type: {self.type} is not valid.")
def _load_config(self): def _load_config(self):
log.debug("def gpgkey._load_config(self)") log.debug("def keygen._load_config(self)")
self.config = configparser.RawConfigParser() self.config = configparser.RawConfigParser()
config_dir = os.path.join(os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')), 'dpgpid') config_dir = os.path.join(os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')), 'dpgpid')
log.debug("config_dir=%s" % config_dir) log.debug("config_dir=%s" % config_dir)
self.config.read( [config_dir + '/gpgkey.conf'] ) self.config.read( [config_dir + '/keygen.conf'] )
def base58_from_ed25519(self): def base58_from_ed25519(self):
log.debug("def gpgkey.base58_from_ed25519(self)") log.debug("def keygen.base58_from_ed25519(self)")
self.base58_public_key = base58.b58encode(self.ed25519_public_key).decode('ascii') self.base58_public_key = base58.b58encode(self.ed25519_public_bytes).decode('ascii')
self.base58_secret_key = base58.b58encode(self.ed25519_secret_key).decode('ascii') self.base58_secret_key = base58.b58encode(self.ed25519_secret_bytes).decode('ascii')
log.debug("self.base58_public_key=%s" % self.base58_public_key) log.debug("self.base58_public_key=%s" % self.base58_public_key)
log.debug("self.base58_secret_key=%s" % self.base58_secret_key) log.debug("self.base58_secret_key=%s" % self.base58_secret_key)
def base58_from_pubsec(self):
log.debug("def keygen.base58_from_pubsec(self)")
for line in open(self.input, "r"):
if re.search("pub", line):
self.base58_public_key = line.replace('\n','').split(': ')[1]
elif re.search("sec", line):
self.base58_secret_key = line.replace('\n','').split(': ')[1]
def do_duniter(self): def do_duniter(self):
log.debug("def gpgkey.do_duniter(self)") log.debug("def keygen.do_duniter(self)")
self.duniterpy_from_salt_and_password()
self.ed25519_from_duniterpy()
self.base58_from_ed25519() self.base58_from_ed25519()
if self.output is None: if self.output is None:
print("pub: %s" % self.base58_public_key) print("pub: %s" % self.base58_public_key)
@ -143,67 +158,20 @@ sec: {self.base58_secret_key}
os.chmod(self.output, 0o600) os.chmod(self.output, 0o600)
def do_ipfs(self): def do_ipfs(self):
log.debug("def gpgkey.do_ipfs(self)") log.debug("def keygen.do_ipfs(self)")
if self.input is None:
self.duniterpy_from_salt_and_password()
self.ed25519_from_duniterpy()
self.base58_from_ed25519()
else:
for line in open(self.input, "r"):
if re.search("pub", line):
self.base58_public_key = line.replace('\n','').split(': ')[1]
elif re.search("sec", line):
self.base58_secret_key = line.replace('\n','').split(': ')[1]
self.ed25519_from_base58()
self.ipfs_from_ed25519() self.ipfs_from_ed25519()
if self.output is None: if self.output is None:
print("PeerID: %s" % self.ipfs_peerid) print("PeerID: %s" % self.ipfs_peerid)
print("PrivKEY: %s" % self.ipfs_privkey) print("PrivKEY: %s" % self.ipfs_privkey)
else: else:
# with open(self.output, "wb") as fh:
# fh.write(self.ipfs_libp2p_protobuf_key)
with open(self.output, "w") as fh: with open(self.output, "w") as fh:
fh.write(f"""Type: PubSec fh.write(self.ed25519_secret_pem_pkcs8)
Version: 1
pub: {self.base58_public_key}
sec: {self.base58_secret_key}
PeerID: {self.ipfs_peerid}
PrivKEY: {self.ipfs_privkey}
"""
)
os.chmod(self.output, 0o600)
def do_pgp(self):
log.debug("def gpgkey.do_pgp(self)")
keys = self.gpg.keylist(pattern=self.username)
pubkeys = list(self.gpg.keylist(pattern=None, secret=False))
seckeys = list(self.gpg.keylist(pattern=None, secret=True))
self.armored_pgp_public_key = self.gpg.key_export(self.username)
self.armored_pgp_secret_key = self.gpg.key_export_secret(self.username)
log.debug("self.armored_pgp_public_key=%s" % self.armored_pgp_public_key)
log.debug("self.armored_pgp_secret_key=%s" % self.armored_pgp_secret_key)
self.pgpy, _ = pgpy.PGPKey.from_blob(self.armored_pgp_secret_key)
log.debug("self.pgpy.fingerprint.keyid=%s" % self.pgpy.fingerprint.keyid)
self.ed25519_from_pgpy()
self.base58_from_ed25519()
self.ipfs_from_ed25519()
if self.output is None:
print("pub: %s" % self.base58_public_key)
print("sec: %s" % self.base58_secret_key)
print("PeerID: %s" % self.ipfs_peerid)
print("PrivKEY: %s" % self.ipfs_privkey)
else:
with open(self.output, "w") as fh:
fh.write(f"""Type: PubSec
Version: 1
pub: {self.base58_public_key}
sec: {self.base58_secret_key}
PeerID: {self.ipfs_peerid}
PrivKEY: {self.ipfs_privkey}
"""
)
os.chmod(self.output, 0o600) os.chmod(self.output, 0o600)
def duniterpy_from_salt_and_password(self): def duniterpy_from_salt_and_password(self):
log.debug("def gpgkey.duniterpy_from_salt_and_password(self)") log.debug("def keygen.duniterpy_from_salt_and_password(self)")
scrypt_params = duniterpy.key.scrypt_params.ScryptParams( 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', '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', 'r')) if self.config.has_option('scrypt', 'r') else 16,
@ -216,54 +184,84 @@ PrivKEY: {self.ipfs_privkey}
scrypt_params scrypt_params
) )
def ed25519(self, args):
log.debug("def keygen.ed25519(self, args)")
if args.gpg is True:
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()
def ed25519_from_base58(self): def ed25519_from_base58(self):
log.debug("def gpgkey.ed25519_from_base58(self)") log.debug("def keygen.ed25519_from_base58(self)")
self.ed25519_public_key = base58.b58decode(self.base58_public_key) self.ed25519_public_bytes = base58.b58decode(self.base58_public_key)
self.ed25519_secret_key = base58.b58decode(self.base58_secret_key) self.ed25519_secret_bytes = base58.b58decode(self.base58_secret_key)
log.debug("self.ed25519_public_key=%s" % self.ed25519_public_key) log.debug("self.ed25519_public_bytes=%s" % self.ed25519_public_bytes)
log.debug("self.ed25519_secret_key=%s" % self.ed25519_secret_key) log.debug("self.ed25519_secret_bytes=%s" % self.ed25519_secret_bytes)
def ed25519_from_duniterpy(self): def ed25519_from_duniterpy(self):
log.debug("def gpgkey.ed25519_from_duniterpy(self)") log.debug("def keygen.ed25519_from_duniterpy(self)")
self.ed25519_public_key = base58.b58decode(self.duniterpy.pubkey) self.ed25519_public_bytes = base58.b58decode(self.duniterpy.pubkey)
self.ed25519_secret_key = self.duniterpy.sk self.ed25519_secret_bytes = self.duniterpy.sk
log.debug("self.ed25519_public_key=%s" % self.ed25519_public_key) log.debug("self.ed25519_public_bytes=%s" % self.ed25519_public_bytes)
log.debug("self.ed25519_secret_key=%s" % self.ed25519_secret_key) log.debug("self.ed25519_secret_bytes=%s" % self.ed25519_secret_bytes)
def ed25519_from_gpg(self):
log.debug("def keygen.ed25519_from_gpg(self)")
self.gpg_pubkeys = list(self.gpg.keylist(pattern=self.username, secret=False))
self.gpg_seckeys = list(self.gpg.keylist(pattern=self.username, secret=True))
log.debug("self.gpg_pubkeys=%s" % self.gpg_pubkeys)
log.debug("self.gpg_seckeys=%s" % self.gpg_seckeys)
self.gpg_seckey = self.gpg_seckeys[0]
log.debug("self.gpg_seckey.fpr=%s" % self.gpg_seckey.fpr)
log.debug("self.gpg_seckey.key=%s" % self.gpg_seckey.__repr__)
self.armored_pgp_public_key = self.gpg.key_export(self.gpg_seckey.fpr)
self.armored_pgp_secret_key = self.gpg.key_export_secret(self.gpg_seckey.fpr)
log.debug("self.armored_pgp_public_key=%s" % self.armored_pgp_public_key)
log.debug("self.armored_pgp_secret_key=%s" % self.armored_pgp_secret_key)
self.pgpy, _ = pgpy.PGPKey.from_blob(self.armored_pgp_secret_key)
log.debug("self.pgpy.fingerprint.keyid=%s" % self.pgpy.fingerprint.keyid)
self.ed25519_from_pgpy()
def ed25519_from_pgpy(self): def ed25519_from_pgpy(self):
log.debug("def gpgkey.ed25519_from_pgpy(self)") log.debug("def keygen.ed25519_from_pgpy(self)")
self.pgpy_key_seed() self.pgpy_key_seed()
self.ed25519_public_key, self.ed25519_secret_key = nacl.bindings.crypto_sign_seed_keypair(self.pgpy_key_seed) self.ed25519_public_bytes, self.ed25519_secret_bytes = nacl.bindings.crypto_sign_seed_keypair(self.pgpy_key_seed)
log.debug("self.ed25519_public_key=%s" % self.ed25519_public_key) log.debug("self.ed25519_public_bytes=%s" % self.ed25519_public_bytes)
log.debug("self.ed25519_secret_key=%s" % self.ed25519_secret_key) log.debug("self.ed25519_secret_bytes=%s" % self.ed25519_secret_bytes)
def ipfs_from_ed25519(self): def ipfs_from_ed25519(self):
log.debug("def ipfs_from_ed25519(self)") log.debug("def keygen.ipfs_from_ed25519(self)")
# Decoding keys # PeerID
ipfs_shared = ed25519.Ed25519PublicKey.from_public_bytes(self.ed25519_public_key) ipfs_pid = base58.b58encode(b'\x00$\x08\x01\x12 ' + self.ed25519_public_bytes)
ipfs_secure = ed25519.Ed25519PrivateKey.from_private_bytes(self.ed25519_secret_key[:32])
ipfs_shared_bytes = ipfs_shared.public_bytes(encoding=serialization.Encoding.Raw,
format=serialization.PublicFormat.Raw)
ipfs_secure_bytes = ipfs_secure.private_bytes(encoding=serialization.Encoding.Raw,
format=serialization.PrivateFormat.Raw,
encryption_algorithm=serialization.NoEncryption())
# Formulating PeerID
ipfs_pid = base58.b58encode(b'\x00$\x08\x01\x12 ' + ipfs_shared_bytes)
self.ipfs_peerid = ipfs_pid.decode('ascii') self.ipfs_peerid = ipfs_pid.decode('ascii')
# Serializing private key in IPFS-native mode, the private key contains public one
pkey = crypto_pb2.PrivateKey()
#pkey.Type = crypto_pb2.KeyType.Ed25519
pkey.Type = 1
pkey.Data = ipfs_secure_bytes + ipfs_shared_bytes
self.ipfs_privkey = base64.b64encode(pkey.SerializeToString()).decode('ascii')
log.debug("self.ipfs_peerid=%s" % self.ipfs_peerid) log.debug("self.ipfs_peerid=%s" % self.ipfs_peerid)
# PrivKey
pkey = crypto_pb2.PrivateKey()
pkey.Type = crypto_pb2.KeyType.Ed25519
pkey.Data = self.ed25519_secret_bytes
self.ipfs_privkey = base64.b64encode(pkey.SerializeToString()).decode('ascii')
log.debug("self.ipfs_privkey=%s" % self.ipfs_privkey) log.debug("self.ipfs_privkey=%s" % self.ipfs_privkey)
# libp2p-protobuf-cleartext format for ipfs key import
self.ipfs_libp2p_protobuf_key = pkey.SerializeToString()
# pem-pkcs8-cleartext format for ipfs key import
self.pem_pkcs8_from_ed25519()
def pem_pkcs8_from_ed25519(self):
log.debug("def keygen.pem_pkcs8_from_ed25519(self)")
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("self.ed25519_secret_pem_pkcs8=%s" % self.ed25519_secret_pem_pkcs8)
def pgpy_key_flags(self): def pgpy_key_flags(self):
log.debug("def gpgkey.pgpy_key_flags(self)") log.debug("def keygen.pgpy_key_flags(self)")
flags = [] flags = []
strs = {pgpy.constants.KeyFlags.Certify : 'C', strs = {pgpy.constants.KeyFlags.Certify : 'C',
pgpy.constants.KeyFlags.Sign : 'S', pgpy.constants.KeyFlags.Sign : 'S',
@ -275,19 +273,25 @@ PrivKEY: {self.ipfs_privkey}
self.pgpy_key_flags = "".join(strs.get(flag, '') for flag in flags) self.pgpy_key_flags = "".join(strs.get(flag, '') for flag in flags)
def pgpy_key_seed(self): def pgpy_key_seed(self):
log.debug("def gpgkey.pgpy_key_seed(self)") log.debug("def keygen.pgpy_key_seed(self)")
self.pgpy_key_type() self.pgpy_key_type()
# todo : unlock password protected key # todo : unlock password protected key
# todo : choose a custom seed for RSA # assert self.pgpy.is_unlocked
assert self.pgpy.is_unlocked if self.pgpy_key_type == 'RSA':
if self.pgpy_key_type == 'RSA.disabled': log.debug("self.pgpy._key.keymaterial.p=%s" % self.pgpy._key.keymaterial.p)
log.debug("self.pgpy._key.keymaterial.q=%s" % self.pgpy._key.keymaterial.q)
# custom seed: use sha256 hash of (p + q)
self.pgpy_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) p = long_to_bytes(self.pgpy._key.keymaterial.p)
q = long_to_bytes(self.pgpy._key.keymaterial.q) q = long_to_bytes(self.pgpy._key.keymaterial.q)
self.pgpy_key_value = "".join([f"{c:02x}" for c in p]) + "".join([f"{c:02x}" for c in q]) self.pgpy_key_value = "".join([f"{c:02x}" for c in p]) + "".join([f"{c:02x}" for c in q])
self.pgpy_key_size = (len(p) + len(q)) * 8 self.pgpy_key_size = (len(p) + len(q)) * 8
log.debug("self.pgpy_key_seed=%s" % self.pgpy_key_seed)
log.debug("self.pgpy_key_value=%s" % self.pgpy_key_value) log.debug("self.pgpy_key_value=%s" % self.pgpy_key_value)
log.debug("self.pgpy_key_size=%s" % self.pgpy_key_size) log.debug("self.pgpy_key_size=%s" % self.pgpy_key_size)
log.debug("self.pgpy._key.keymaterial.encbytes=%s" % self.pgpy._key.keymaterial.encbytes)
elif self.pgpy_key_type in ('ECDSA', 'EdDSA', 'ECDH'): elif self.pgpy_key_type in ('ECDSA', 'EdDSA', 'ECDH'):
log.debug("self.pgpy._key.keymaterial.s=%s" % self.pgpy._key.keymaterial.s)
self.pgpy_key_seed = long_to_bytes(self.pgpy._key.keymaterial.s) self.pgpy_key_seed = long_to_bytes(self.pgpy._key.keymaterial.s)
self.pgpy_key_value = "".join([f"{c:02x}" for c in self.pgpy_key_seed]) self.pgpy_key_value = "".join([f"{c:02x}" for c in self.pgpy_key_seed])
self.pgpy_key_size = len(self.pgpy_key_seed)*8 self.pgpy_key_size = len(self.pgpy_key_seed)*8
@ -298,7 +302,7 @@ PrivKEY: {self.ipfs_privkey}
raise NotImplementedError(f"Get seed from {self.pgpy_key_type} key is not supported") raise NotImplementedError(f"Get seed from {self.pgpy_key_type} key is not supported")
def pgpy_key_type(self): def pgpy_key_type(self):
log.debug("def gpgkey.pgpy_key_type(self)") log.debug("def keygen.pgpy_key_type(self)")
if isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.RSAPriv): if isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.RSAPriv):
self.pgpy_key_type = 'RSA' self.pgpy_key_type = 'RSA'
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.DSAPriv): elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.DSAPriv):
@ -337,11 +341,12 @@ PrivKEY: {self.ipfs_privkey}
log_level='WARNING' log_level='WARNING'
log.basicConfig(format=log_format, datefmt=log_datefmt, level=log_level) log.basicConfig(format=log_format, datefmt=log_datefmt, level=log_level)
self._check_args() self._check_args(args)
self._load_config() self._load_config()
# self.gpg = gpg.Context(armor=True, offline=True, homedir=GNUPGHOME) # self.gpg = gpg.Context(armor=True, offline=True, homedir=GNUPGHOME)
self.gpg = gpg.Context(armor=True, offline=True) self.gpg = gpg.Context(armor=True, offline=True)
method = getattr(self, f'do_{self.command}', self._invalid_command) self.ed25519(args)
method = getattr(self, f'do_{self.type}', self._invalid_type)
return method() return method()
# long_to_bytes comes from PyCrypto, which is released into Public Domain # long_to_bytes comes from PyCrypto, which is released into Public Domain
@ -396,7 +401,7 @@ def main(argv=None):
if argv is None: if argv is None:
argv = sys.argv[1:] argv = sys.argv[1:]
cli = gpgkey() cli = keygen()
return cli.run(argv) return cli.run(argv)
def version(version=__version__): def version(version=__version__):

View File

@ -1,139 +0,0 @@
#shellcheck shell=sh
set -eu
gpgkey() {
if [ -x ./gpgkey ]; then
./gpgkey "$@"
elif [ -x ./bin/gpgkey ]; then
./bin/gpgkey "$@"
else
gpgkey "$@"
fi
}
Describe 'Dependency'
Describe 'python3:'
It 'is available'
When run python3 --help
The output should include "python3"
The status should be success
The stderr should equal ""
End
End
End
Describe 'gpgkey'
Describe '--help:'
It 'prints help'
When run gpgkey --help
The output should include 'usage:'
The status should be success
The stderr should equal ""
End
End
Describe '--version:'
It 'prints version'
When run gpgkey --version
The output should include 'v0.0.1'
The status should be success
The stderr should equal ""
End
End
Describe 'duniter username password:'
It 'prints duniter keys for user username'
When run gpgkey duniter username password
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should equal ""
End
End
Describe 'duniter username password -o /tmp/test_gpgkey_duniter.pubsec:'
rm -f /tmp/test_gpgkey_duniter.pubsec
It 'writes duniter keys to file for user username'
When run gpgkey duniter username password -o /tmp/test_gpgkey_duniter.pubsec
The path '/tmp/test_gpgkey_duniter.pubsec' should exist
The contents of file '/tmp/test_gpgkey_duniter.pubsec' should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The contents of file '/tmp/test_gpgkey_duniter.pubsec' should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should equal ""
End
End
Describe 'ipfs -i /tmp/test_gpgkey_duniter.pubsec:'
It 'prints ipfs keys for duniter keys read in pubsec file'
When run gpgkey ipfs -i /tmp/test_gpgkey_duniter.pubsec
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 equal ""
End
End
Describe 'ipfs -i /tmp/test_gpgkey_duniter.pubsec -o /tmp/test_gpgkey_ipfs.pubsec:'
It 'writes duniter and ipfs keys to file for duniter keys read in pubsec file'
When run gpgkey ipfs -i /tmp/test_gpgkey_duniter.pubsec -o /tmp/test_gpgkey_ipfs.pubsec
The path '/tmp/test_gpgkey_ipfs.pubsec' should exist
The contents of file '/tmp/test_gpgkey_ipfs.pubsec' should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The contents of file '/tmp/test_gpgkey_ipfs.pubsec' should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The contents of file '/tmp/test_gpgkey_ipfs.pubsec' should include 'PeerID: 12D3KooWDMhdm5yrvtrbkshXFjkqLedHieUnPioczy9wzdnzquHC'
The contents of file '/tmp/test_gpgkey_ipfs.pubsec' should include 'PrivKEY: CAESQA+XqCWjRqCjNe9oU3QA796bEH+T+rxgyPQ/EkXvE2MvNJoTbvcP+m51+XwxrmWqHaOpI1ZD0USwLjqAmV8Boas='
The status should be success
The stderr should equal ""
End
rm -f /tmp/test_gpgkey_duniter.pubsec /tmp/test_gpgkey_ipfs.pubsec
End
Describe 'ipfs username password:'
It 'prints ipfs keys for user username'
When run gpgkey ipfs username password
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 equal ""
End
End
Describe 'ipfs username password -o /tmp/test_gpgkey_ipfs.pubsec:'
It 'writes duniter and ipfs keys to file for user username'
When run gpgkey ipfs username password -o /tmp/test_gpgkey_ipfs.pubsec
The path '/tmp/test_gpgkey_ipfs.pubsec' should exist
The contents of file '/tmp/test_gpgkey_ipfs.pubsec' should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The contents of file '/tmp/test_gpgkey_ipfs.pubsec' should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The contents of file '/tmp/test_gpgkey_ipfs.pubsec' should include 'PeerID: 12D3KooWDMhdm5yrvtrbkshXFjkqLedHieUnPioczy9wzdnzquHC'
The contents of file '/tmp/test_gpgkey_ipfs.pubsec' should include 'PrivKEY: CAESQA+XqCWjRqCjNe9oU3QA796bEH+T+rxgyPQ/EkXvE2MvNJoTbvcP+m51+XwxrmWqHaOpI1ZD0USwLjqAmV8Boas='
The status should be success
The stderr should equal ""
End
rm -f /tmp/test_gpgkey_ipfs.pubsec
End
Describe 'pgp username password:'
gpg --import --quiet specs/username.asc
gpg --import --quiet specs/username.pub
It 'creates a gpg key for user username'
Skip "You should implement it !"
When run gpgkey --gen pgp username password
The status should be success
End
End
Describe 'pgp username password:'
It 'prints duniter and ipfs keys for gpg key matching username'
When run gpgkey pgp username password
The output should include 'pub: 2g5UL2zhkn5i7oNYDpWo3fBuWvRYVU1AbMtdVmnGzPNv'
The output should include 'sec: 5WtYFfA26nTfG496gAKhkrLYUMMnwXexmE1E8Q7PvtQEyscHfirsdMzW34zDp7WEkt3exNEVwoG4ajZYrm62wpi2'
The output should include 'PeerID: 12D3KooWBVSe5AaQwgMCXgsxrRG8pTGk1FUBXA5eYxFeskwAtL6r'
The output should include 'PrivKEY: CAESQOHXwPgzoiDca1ZnvhU/W3zdogZXulkoErnUsqt+ut82GN5k4MIbVvz2m6Vq0ij9fQFPNUz+ZZdv2D31K6mzBQc='
The status should be success
The stderr should equal ""
End
End
Describe 'pgp username password -o /tmp/test_gpgkey_pgp.pubsec:'
It 'writes duniter and ipfs keys to file for gpg key matching username'
When run gpgkey pgp username password -o /tmp/test_gpgkey_pgp.pubsec
The path '/tmp/test_gpgkey_pgp.pubsec' should exist
The contents of file '/tmp/test_gpgkey_pgp.pubsec' should include 'pub: 2g5UL2zhkn5i7oNYDpWo3fBuWvRYVU1AbMtdVmnGzPNv'
The contents of file '/tmp/test_gpgkey_pgp.pubsec' should include 'sec: 5WtYFfA26nTfG496gAKhkrLYUMMnwXexmE1E8Q7PvtQEyscHfirsdMzW34zDp7WEkt3exNEVwoG4ajZYrm62wpi2'
The contents of file '/tmp/test_gpgkey_pgp.pubsec' should include 'PeerID: 12D3KooWBVSe5AaQwgMCXgsxrRG8pTGk1FUBXA5eYxFeskwAtL6r'
The contents of file '/tmp/test_gpgkey_pgp.pubsec' should include 'PrivKEY: CAESQOHXwPgzoiDca1ZnvhU/W3zdogZXulkoErnUsqt+ut82GN5k4MIbVvz2m6Vq0ij9fQFPNUz+ZZdv2D31K6mzBQc='
The status should be success
The stderr should equal ""
End
rm -f /tmp/test_gpgkey_pgp.pubsec
End
End

154
specs/keygen_spec.sh Normal file
View File

@ -0,0 +1,154 @@
#shellcheck shell=sh
set -eu
keygen() {
if [ -x ./keygen ]; then
./keygen "$@"
elif [ -x ./bin/keygen ]; then
./bin/keygen "$@"
else
keygen "$@"
fi
}
Describe 'Dependency'
Describe 'python3:'
It 'is available'
When run python3 --help
The output should include "python3"
The status should be success
The stderr should equal ""
End
End
End
Describe 'keygen'
Describe '--help:'
It 'prints help'
When run keygen --help
The output should include 'usage:'
The status should be success
The stderr should equal ""
End
End
Describe '--version:'
It 'prints version'
When run keygen --version
The output should include 'v0.0.1'
The status should be success
The stderr should equal ""
End
End
Describe '-t duniter username password:'
It 'prints duniter keys for user username'
When run keygen -t duniter username password
The output should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The output should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should equal ""
End
End
Describe '-o /tmp/keygen_test_duniter.pubsec -t duniter username password:'
rm -f /tmp/keygen_test_duniter.pubsec
It 'writes duniter keys to file for user username'
When run keygen -o /tmp/keygen_test_duniter.pubsec -t duniter username password
The path '/tmp/keygen_test_duniter.pubsec' should exist
The contents of file '/tmp/keygen_test_duniter.pubsec' should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The contents of file '/tmp/keygen_test_duniter.pubsec' should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
The status should be success
The stderr should equal ""
End
End
Describe '-i /tmp/keygen_test_duniter.pubsec -t ipfs:'
It 'prints ipfs keys for duniter keys read in pubsec file'
When run keygen -i /tmp/keygen_test_duniter.pubsec -t ipfs
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 equal ""
End
End
Describe '-i /tmp/keygen_test_duniter.pubsec -o /tmp/keygen_test_ipfs.pem -t ipfs:'
It 'writes ipfs keys to file for duniter keys read in pubsec file'
When run keygen -i /tmp/keygen_test_duniter.pubsec -o /tmp/keygen_test_ipfs.pem -t ipfs
The path '/tmp/keygen_test_ipfs.pem' should exist
The contents of file '/tmp/keygen_test_ipfs.pem' should include '-----BEGIN PRIVATE KEY-----'
The contents of file '/tmp/keygen_test_ipfs.pem' should include 'MC4CAQAwBQYDK2VwBCIEIA+XqCWjRqCjNe9oU3QA796bEH+T+rxgyPQ/EkXvE2Mv'
The contents of file '/tmp/keygen_test_ipfs.pem' should include '-----END PRIVATE KEY-----'
The status should be success
The stderr should equal ""
End
rm -f /tmp/keygen_test_duniter.pubsec /tmp/keygen_test_ipfs.pem
End
Describe '-t ipfs username password:'
It 'prints ipfs keys for user username'
When run keygen -t ipfs username password
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 equal ""
End
End
Describe '-o /tmp/keygen_test_ipfs.pem -t ipfs username password:'
It 'writes ipfs keys to file for user username'
When run keygen username password -o /tmp/keygen_test_ipfs.pem -t ipfs
The path '/tmp/keygen_test_ipfs.pem' should exist
The contents of file '/tmp/keygen_test_ipfs.pem' should include '-----BEGIN PRIVATE KEY-----'
The contents of file '/tmp/keygen_test_ipfs.pem' should include 'MC4CAQAwBQYDK2VwBCIEIA+XqCWjRqCjNe9oU3QA796bEH+T+rxgyPQ/EkXvE2Mv'
The contents of file '/tmp/keygen_test_ipfs.pem' should include '-----END PRIVATE KEY-----'
The status should be success
The stderr should equal ""
End
rm -f /tmp/keygen_test_ipfs.pem
End
Describe '-t pgp username password birthday:'
gpg --import --quiet specs/username.asc
gpg --import --quiet specs/username.pub
It 'creates a gpg key for user username'
Skip "You should implement it !"
When run keygen -t pgp username password
The status should be success
End
End
Describe '-g -t duniter username:'
It 'prints duniter keys for gpg key matching username'
When run keygen -g -t duniter username
The output should include 'pub: 2g5UL2zhkn5i7oNYDpWo3fBuWvRYVU1AbMtdVmnGzPNv'
The output should include 'sec: 5WtYFfA26nTfG496gAKhkrLYUMMnwXexmE1E8Q7PvtQEyscHfirsdMzW34zDp7WEkt3exNEVwoG4ajZYrm62wpi2'
The status should be success
The stderr should equal ""
End
End
Describe '-g -t ipfs username:'
It 'prints ipfs keys for gpg key matching username'
When run keygen -g -t ipfs username
The output should include 'PeerID: 12D3KooWBVSe5AaQwgMCXgsxrRG8pTGk1FUBXA5eYxFeskwAtL6r'
The output should include 'PrivKEY: CAESQOHXwPgzoiDca1ZnvhU/W3zdogZXulkoErnUsqt+ut82GN5k4MIbVvz2m6Vq0ij9fQFPNUz+ZZdv2D31K6mzBQc='
The status should be success
The stderr should equal ""
End
End
Describe '-g -o /tmp/keygen_test_duniter.pubsec -t duniter username:'
It 'writes duniter keys to file for gpg key matching username'
When run keygen -g -o /tmp/keygen_test_duniter.pubsec -t duniter username
The path '/tmp/keygen_test_duniter.pubsec' should exist
The contents of file '/tmp/keygen_test_duniter.pubsec' should include 'pub: 2g5UL2zhkn5i7oNYDpWo3fBuWvRYVU1AbMtdVmnGzPNv'
The contents of file '/tmp/keygen_test_duniter.pubsec' should include 'sec: 5WtYFfA26nTfG496gAKhkrLYUMMnwXexmE1E8Q7PvtQEyscHfirsdMzW34zDp7WEkt3exNEVwoG4ajZYrm62wpi2'
The status should be success
The stderr should equal ""
End
rm -f /tmp/keygen_test_duniter.pubsec
End
Describe '-g -o /tmp/keygen_test_ipfs.pem -t ipfs username:'
It 'writes ipfs keys to file for gpg key matching username'
When run keygen -g -o /tmp/keygen_test_ipfs.pem -t ipfs username
The path '/tmp/keygen_test_ipfs.pem' should exist
The contents of file '/tmp/keygen_test_ipfs.pem' should include '-----BEGIN PRIVATE KEY-----'
The contents of file '/tmp/keygen_test_ipfs.pem' should include 'MC4CAQAwBQYDK2VwBCIEIOHXwPgzoiDca1ZnvhU/W3zdogZXulkoErnUsqt+ut82'
The contents of file '/tmp/keygen_test_ipfs.pem' should include '-----END PRIVATE KEY-----'
The status should be success
The stderr should equal ""
End
rm -f /tmp/keygen_test_ipfs.pem
End
End