wip: export keys from gpg

This commit is contained in:
Yann Autissier 2022-05-21 03:37:51 +02:00
parent 48887c6102
commit 5bab667215
10 changed files with 363 additions and 92 deletions

0
.shellspec Normal file
View File

View File

@ -1,4 +1,5 @@
-include $(if $(MYOS),$(MYOS),../myos)/make/include.mk
MYOS ?= ../myos
-include $(MYOS)/make/include.mk
PREFIX ?= /usr/local
BINDIR ?= $(PREFIX)/bin
@ -14,7 +15,7 @@ install:
install dpgpid "$(BINDIR)/dpgpid"
shellcheck-%:
shellcheck $*/*
shellcheck $*/*.sh
shellspec-%:
shellspec -f tap $*

View File

@ -10,7 +10,6 @@ services:
- USER=${USER}
context: ..
dockerfile: docker/dpgpid/Dockerfile
command: tail -f /dev/null
image: ${DOCKER_REPOSITORY}/dpgpid:${DOCKER_IMAGE_TAG}
networks:
- private

View File

@ -9,44 +9,51 @@ ARG PYTHON_RELEASE=3.10
WORKDIR /opt/dpgpid
COPY requirements.txt ./
RUN apk add --no-cache --virtual .build-deps \
g++ \
RUN apk upgrade --no-cache \
&& apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/ --virtual .build-deps \
build-base \
libffi-dev \
protobuf \
py3-gpgme \
swig \
&& /usr/local/bin/python${PYTHON_RELEASE} -m venv ./ \
&& ./bin/pip${PYTHON_RELEASE} install -U pip wheel \
&& ./bin/pip${PYTHON_RELEASE} install -r ./requirements.txt \
&& wget https://github.com/libp2p/go-libp2p-core/raw/master/crypto/pb/crypto.proto \
&& protoc --python_out=./lib/python${PYTHON_RELEASE}/site-packages/ crypto.proto \
&& cp -a /usr/lib/python${PYTHON_RELEASE}/site-packages/gpg ./lib/python${PYTHON_RELEASE}/site-packages/ \
&& rm -rf /root/.cache ./build ./crypto.proto \
&& apk del --no-network .build-deps \
&& find ./lib -type f -executable \
-exec scanelf --needed --nobanner --format '%n#p' '{}' ';' \
&& find ./lib -type f -executable -exec scanelf --needed --nobanner --format '%n#p' '{}' ';' \
|tr ',' '\n' \
|sort -u \
| awk 'system("[ -e /lib/"$1" -o -e /usr/lib/"$1" -o -e /opt/dpgpid/lib/python'"${PYTHON_RELEASE}"'/site-packages/*/"$1" ]") == 0 { next } { print "so:" $1 }' \
| xargs -rt apk add --no-cache
|awk 'system("[ -e /lib/"$1" -o -e /usr/lib/"$1" -o -e ./lib/python'"${PYTHON_RELEASE}"'/site-packages/*/"$1" ]") == 0 { next } { print "so:" $1 }' \
|xargs -rt apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/community/
RUN apk add --repository https://dl-cdn.alpinelinux.org/alpine/edge/testing \
envsubst \
&& apk add --no-cache \
RUN apk add --no-cache \
bash \
ca-certificates \
gettext \
gpg \
gpg-agent \
libc6-compat \
libsodium \
make \
gpg \
&& OS="$(echo ${OPERATING_SYSTEM} |awk '{print tolower($0)}')"; \
ARCH="$(echo ${PROCESSOR_ARCHITECTURE})"; \
wget -qO - https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.${OS}.${ARCH}.tar.xz |tar --strip-components 1 -C /usr/local/bin -xJf - \
&& mkdir -p /usr/local/lib/shellspec \
&& wget -qO - https://github.com/shellspec/shellspec/archive/latest.tar.gz |tar --strip-components 1 -C /usr/local/lib/shellspec -xzf - \
&& ln -s /usr/local/lib/shellspec/shellspec /usr/local/bin/shellspec
wget -qO - https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.${OS}.${ARCH}.tar.xz \
|tar --strip-components 1 -C ./bin -xJf - \
&& mkdir -p /opt/shellspec \
&& wget -qO - https://github.com/shellspec/shellspec/archive/refs/heads/master.tar.gz \
|tar --strip-components 1 -C /opt/shellspec -xzf - \
&& ln -s /opt/shellspec/shellspec ./bin/shellspec
COPY --from=ipfs/go-ipfs:v0.13.0-rc1 /usr/local/bin/ipfs /usr/local/bin/
COPY --from=ipfs/go-ipfs:v0.13.0-rc1 /usr/local/bin/ipfs ./bin/
COPY README.md ./
COPY COPYING ./
COPY Makefile ./
COPY .shellspec ./
COPY specs/ ./specs/
COPY dpgpid ./bin/dpgpid
COPY gpgkey ./bin/gpgkey

251
gpgkey
View File

@ -1,10 +1,14 @@
#!/usr/bin/env python3
# link: https://git.p2p.legal/aya/dpgpid/
# desc: gpgkey converts ed25519 gpg keys to match duniter and ipfs format
# desc: gpgkey converts ed25519 gpg keys to ed25519 duniter and ipfs keys
# Copyleft 2022 Yann Autissier <aya@asycn.io>
# all crypto science belongs to Pascal Engélibert <tuxmain@zettascript.org>
# coming from files available at https://git.p2p.legal/qo-op/Astroport.ONE/tools
# gpgme stuff has been provided by Ben McGinnes
# and comes from http://files.au.adversary.org/crypto/gpgme-python-howto.html
# gpg key extraction is taken from work of Simon Vareille available at
# https://gist.github.com/SimonVareille/fda49baf5f3e15b5c88e25560aeb2822
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
@ -27,9 +31,13 @@ import crypto_pb2
import cryptography.hazmat.primitives.asymmetric.ed25519 as ed25519
from cryptography.hazmat.primitives import serialization
import duniterpy.key
import gpg
import nacl.bindings
import pgpy
import logging as log
import os
import re
import struct
import sys
import time
@ -80,8 +88,7 @@ class gpgkey:
help="duniter|ipfs",
nargs="?",
)
self.parser.add_argument(
'username',
self.parser.add_argument( 'username',
nargs="?",
)
self.parser.add_argument(
@ -90,53 +97,113 @@ class gpgkey:
)
def _check_args(self):
log.debug("func gpgkey._check_args(self)")
log.debug("var self.command: %s" % self.command)
log.debug("var self.username: %s" % self.username)
log.debug("var self.password: %s" % self.password)
log.debug("def gpgkey._check_args(self)")
log.debug("self.command=%s" % self.command)
log.debug("self.username=%s" % self.username)
log.debug("self.password=%s" % self.password)
if self.command:
if self.input is None:
if self.password is None or self.username is None:
self.parser.error(f"{self.command} requires an input file or username and password args")
def _invalid_command(self):
log.debug("func gpgkey._invalid_command(self)")
log.debug("def gpgkey._invalid_command(self)")
self.parser.error(f"{self.command} is not a valid command.")
def _load_config(self):
log.debug("func gpgkey._load_config(self)")
log.debug("def gpgkey._load_config(self)")
self.config = configparser.RawConfigParser()
config_dir = os.path.join(os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')), 'dpgpid')
log.debug("var config_dir: %s" % config_dir)
log.debug("config_dir=%s" % config_dir)
self.config.read( [config_dir + '/gpgkey.conf'] )
def base58_from_ed25519(self):
log.debug("def gpgkey.base58_from_ed25519(self)")
self.base58_public_key = base58.b58encode(self.ed25519_public_key).decode('ascii')
self.base58_secret_key = base58.b58encode(self.ed25519_secret_key).decode('ascii')
log.debug("self.base58_public_key=%s" % self.base58_public_key)
log.debug("self.base58_secret_key=%s" % self.base58_secret_key)
def do_duniter(self):
log.debug("func gpgkey.do_duniter(self)")
log.debug("def gpgkey.do_duniter(self)")
self.duniterpy_from_salt_and_password()
print(self.duniterpy.pubkey)
if self.output is not None:
self.duniterpy.save_pubsec_file(self.output)
self.ed25519_from_duniterpy()
self.base58_from_ed25519()
if self.output is None:
print("pub: %s" % self.base58_public_key)
print("sec: %s" % self.base58_secret_key)
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}
"""
)
os.chmod(self.output, 0o600)
def do_ipfs(self):
log.info("func do_ipfs(self)")
log.debug("def gpgkey.do_ipfs(self)")
if self.input is None:
self.duniterpy_from_salt_and_password()
self.ipfs_base58_shared_key=self.duniterpy.pubkey
self.ipfs_base58_secure_key=base58.b58encode(self.duniterpy.sk)
self.ed25519_from_duniterpy()
self.base58_from_ed25519()
else:
for line in open(self.input, "r"):
if re.search("pub", line):
self.ipfs_base58_shared_key=line.replace('\n','').split(': ')[1]
self.base58_public_key = line.replace('\n','').split(': ')[1]
elif re.search("sec", line):
self.ipfs_base58_secure_key=line.replace('\n','').split(': ')[1]
self.base58_secret_key = line.replace('\n','').split(': ')[1]
self.ed25519_from_base58()
self.ipfs_from_ed25519()
if self.output is None:
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)
self.ipfs_from_ed25519_key()
print('PeerID={}'.format(self.ipfs_peerid))
print('PrivKEY={}'.format(self.ipfs_privkey))
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)
def duniterpy_from_salt_and_password(self):
log.debug("func gpgkey.duniterpy_from_salt_and_password(self)")
log.debug("def gpgkey.duniterpy_from_salt_and_password(self)")
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,
@ -149,14 +216,33 @@ class gpgkey:
scrypt_params
)
def ipfs_from_ed25519_key(self):
log.info("func ipfs_from_ed25519_key(self)")
def ed25519_from_base58(self):
log.debug("def gpgkey.ed25519_from_base58(self)")
self.ed25519_public_key = base58.b58decode(self.base58_public_key)
self.ed25519_secret_key = base58.b58decode(self.base58_secret_key)
log.debug("self.ed25519_public_key=%s" % self.ed25519_public_key)
log.debug("self.ed25519_secret_key=%s" % self.ed25519_secret_key)
def ed25519_from_duniterpy(self):
log.debug("def gpgkey.ed25519_from_duniterpy(self)")
self.ed25519_public_key = base58.b58decode(self.duniterpy.pubkey)
self.ed25519_secret_key = self.duniterpy.sk
log.debug("self.ed25519_public_key=%s" % self.ed25519_public_key)
log.debug("self.ed25519_secret_key=%s" % self.ed25519_secret_key)
def ed25519_from_pgpy(self):
log.debug("def gpgkey.ed25519_from_pgpy(self)")
self.pgpy_key_seed()
self.ed25519_public_key, self.ed25519_secret_key = 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_secret_key=%s" % self.ed25519_secret_key)
def ipfs_from_ed25519(self):
log.debug("def ipfs_from_ed25519(self)")
# Decoding keys
decoded_shared = base58.b58decode(self.ipfs_base58_shared_key)
decoded_secure = base58.b58decode(self.ipfs_base58_secure_key)
ipfs_shared = ed25519.Ed25519PublicKey.from_public_bytes(decoded_shared)
ipfs_secure = ed25519.Ed25519PrivateKey.from_private_bytes(decoded_secure[:32])
ipfs_shared = ed25519.Ed25519PublicKey.from_public_bytes(self.ed25519_public_key)
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,
@ -165,7 +251,6 @@ class gpgkey:
# Formulating PeerID
ipfs_pid = base58.b58encode(b'\x00$\x08\x01\x12 ' + ipfs_shared_bytes)
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
@ -173,8 +258,62 @@ class gpgkey:
#pkey.Type = crypto_pb2.KeyType.Ed25519
pkey.Type = 1
pkey.Data = ipfs_secure_bytes + ipfs_shared_bytes
PrivKey = base64.b64encode(pkey.SerializeToString()).decode('ascii')
self.ipfs_privkey = base64.b64encode(pkey.SerializeToString()).decode('ascii')
log.debug("self.ipfs_peerid=%s" % self.ipfs_peerid)
log.debug("self.ipfs_privkey=%s" % self.ipfs_privkey)
def pgpy_key_flags(self):
log.debug("def gpgkey.pgpy_key_flags(self)")
flags = []
strs = {pgpy.constants.KeyFlags.Certify : 'C',
pgpy.constants.KeyFlags.Sign : 'S',
pgpy.constants.KeyFlags.EncryptCommunications : 'E',
pgpy.constants.KeyFlags.Authentication : 'A'}
for sig in self.pgpy.self_signatures:
if not sig.is_expired:
flags += sig.key_flags
self.pgpy_key_flags = "".join(strs.get(flag, '') for flag in flags)
def pgpy_key_seed(self):
log.debug("def gpgkey.pgpy_key_seed(self)")
self.pgpy_key_type()
# todo : unlock password protected key
# todo : choose a custom seed for RSA
assert self.pgpy.is_unlocked
if self.pgpy_key_type == 'RSA.disabled':
p = long_to_bytes(self.pgpy._key.keymaterial.p)
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_size = (len(p) + len(q)) * 8
log.debug("self.pgpy_key_value=%s" % self.pgpy_key_value)
log.debug("self.pgpy_key_size=%s" % self.pgpy_key_size)
elif self.pgpy_key_type in ('ECDSA', 'EdDSA', 'ECDH'):
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_size = len(self.pgpy_key_seed)*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_size=%s" % self.pgpy_key_size)
else:
raise NotImplementedError(f"Get seed from {self.pgpy_key_type} key is not supported")
def pgpy_key_type(self):
log.debug("def gpgkey.pgpy_key_type(self)")
if isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.RSAPriv):
self.pgpy_key_type = 'RSA'
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.DSAPriv):
self.pgpy_key_type = 'DSA'
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.ElGPriv):
self.pgpy_key_type = 'ElGamal'
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.ECDSAPriv):
self.pgpy_key_type = 'ECDSA'
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.EdDSAPriv):
self.pgpy_key_type = 'EdDSA'
elif isinstance(self.pgpy._key.keymaterial, pgpy.packet.fields.ECDHPriv):
self.pgpy_key_type = 'ECDH'
else:
self.pgpy_key_type = 'undefined'
log.debug("self.pgpy_key_type=%s" % self.pgpy_key_type)
def run(self, argv):
args = self.parser.parse_args(argv)
@ -200,9 +339,59 @@ class gpgkey:
self._check_args()
self._load_config()
# self.gpg = gpg.Context(armor=True, offline=True, homedir=GNUPGHOME)
self.gpg = gpg.Context(armor=True, offline=True)
method = getattr(self, f'do_{self.command}', self._invalid_command)
return method()
# long_to_bytes comes from PyCrypto, which is released into Public Domain
# https://github.com/dlitz/pycrypto/blob/master/lib/Crypto/Util/number.py
def bytes_to_long(s):
"""bytes_to_long(string) : long
Convert a byte string to a long integer.
This is (essentially) the inverse of long_to_bytes().
"""
acc = 0
unpack = struct.unpack
length = len(s)
if length % 4:
extra = (4 - length % 4)
s = b'\000' * extra + s
length = length + extra
for i in range(0, length, 4):
acc = (acc << 32) + unpack('>I', s[i:i+4])[0]
return acc
def long_to_bytes(n, blocksize=0):
"""long_to_bytes(n:long, blocksize:int) : string
Convert a long integer to a byte string.
If optional blocksize is given and greater than zero, pad the front of the
byte string with binary zeros so that the length is a multiple of
blocksize.
"""
# after much testing, this algorithm was deemed to be the fastest
s = b''
n = int(n)
pack = struct.pack
while n > 0:
s = pack('>I', n & 0xffffffff) + s
n = n >> 32
# strip off leading zeros
for i in range(len(s)):
if s[i] != b'\000'[0]:
break
else:
# only happens when n == 0
s = b'\000'
i = 0
s = s[i:]
# add back some pad bytes. this could be done more efficiently w.r.t. the
# de-padding being done above, but sigh...
if blocksize > 0 and len(s) % blocksize:
s = (blocksize - len(s) % blocksize) * b'\000' + s
return s
def main(argv=None):
if argv is None:
argv = sys.argv[1:]

View File

@ -1,7 +1,7 @@
argparse
base58
configparser
cryptography
duniterpy
google
pgpy
protobuf
pynacl

View File

@ -12,26 +12,18 @@ dpgpid() {
}
Describe 'Dependency'
Describe 'awk'
Describe 'gpg:'
It 'is available'
When run which awk
The output should include "/awk"
When run gpg --help
The output should include "gpg"
The status should be success
The stderr should equal ""
End
End
Describe 'gpg'
Describe 'ipfs:'
It 'is available'
When run which gpg
The output should include "/gpg"
The status should be success
The stderr should equal ""
End
End
Describe 'ipfs'
It 'is available'
When run which ipfs
The output should include "/ipfs"
When run ipfs --help
The output should include "ipfs"
The status should be success
The stderr should equal ""
End
@ -39,7 +31,7 @@ Describe 'Dependency'
End
Describe 'dpgpid'
Describe '--help'
Describe '--help:'
It 'prints help'
When run dpgpid --help
The output should include 'Usage:'
@ -47,7 +39,7 @@ Describe 'dpgpid'
The stderr should equal ""
End
End
Describe '--version'
Describe '--version:'
It 'prints version'
When run dpgpid --version
The output should include 'v0.0.1'

View File

@ -12,10 +12,10 @@ gpgkey() {
}
Describe 'Dependency'
Describe 'python3'
Describe 'python3:'
It 'is available'
When run which python3
The output should include "/python3"
When run python3 --help
The output should include "python3"
The status should be success
The stderr should equal ""
End
@ -23,7 +23,7 @@ Describe 'Dependency'
End
Describe 'gpgkey'
Describe '--help'
Describe '--help:'
It 'prints help'
When run gpgkey --help
The output should include 'usage:'
@ -31,7 +31,7 @@ Describe 'gpgkey'
The stderr should equal ""
End
End
Describe '--version'
Describe '--version:'
It 'prints version'
When run gpgkey --version
The output should include 'v0.0.1'
@ -39,35 +39,101 @@ Describe 'gpgkey'
The stderr should equal ""
End
End
Describe 'duniter username password -o /tmp/test_gpgkey'
rm -f /tmp/test_gpgkey
It 'prints duniter public key and write duniter keys to file /tmp/test_gpgkey for user username'
When run gpgkey duniter username password -o /tmp/test_gpgkey
The output should eq '4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The path '/tmp/test_gpgkey' should exist
The contents of file '/tmp/test_gpgkey' should include 'pub: 4YLU1xQ9jzb7LzC6d91VZrYTEKS9N2j93Nnvcee6wxZG'
The contents of file '/tmp/test_gpgkey' should include 'sec: K5heSX4xGUPtRbxcZh6zbgaKbDv8FeVc9JuSNWtUs7C1oGNKqv7kQJ3DHdouTPzoW4duKKnuLQK8LbHKfN9fkjC'
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 'ipfs -i /tmp/test_gpgkey'
It 'prints ipfs PeerID and PrivKEY for duniter keys in file /tmp/test_gpgkey'
When run gpgkey ipfs -i /tmp/test_gpgkey
The output should include 'PeerID=12D3KooWDMhdm5yrvtrbkshXFjkqLedHieUnPioczy9wzdnzquHC'
The output should include 'PrivKEY=CAESQA+XqCWjRqCjNe9oU3QA796bEH+T+rxgyPQ/EkXvE2MvNJoTbvcP+m51+XwxrmWqHaOpI1ZD0USwLjqAmV8Boas='
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
rm -f /tmp/test_gpgkey
End
Describe 'ipfs username password'
It 'prints ipfs PeerID and PrivKEY for user username'
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 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

9
specs/username.asc Normal file
View File

@ -0,0 +1,9 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----
xVgEAAAAABYJKwYBBAHaRw8BAQdAGN5k4MIbVvz2m6Vq0ij9fQFPNUz+ZZdv2D31
K6mzBQcAAQDh18D4M6Ig3GtWZ74VP1t83aIGV7pZKBK51LKrfrrfNhCzzQh1c2Vy
bmFtZcJhBBMWCAATBQIAAAAACRAHnlv0chlE+wIbAwAAlzwBAIbSTs0OhkTDykx1
bqogkOG8lKRY8vVARJnehvcOWf7QAP9GpuySQHL041bDdkBJVXeofSmp3QfR6ZxG
D0VoQE2NCQ==
=7FCh
-----END PGP PRIVATE KEY BLOCK-----

8
specs/username.pub Normal file
View File

@ -0,0 +1,8 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
xjMEAAAAABYJKwYBBAHaRw8BAQdAGN5k4MIbVvz2m6Vq0ij9fQFPNUz+ZZdv2D31
K6mzBQfNCHVzZXJuYW1lwmEEExYIABMFAmKD2B0JEAeeW/RyGUT7AhsDAADy8AD/
QvC5UvW8TVUdbCd0EQvPjlfVzRauBlxQP4oy+vjnItcA/R1RgGS0D9zAGHC6CRHt
AwxzDz3dIpKQAJxxliD8ZO0G
=51r3
-----END PGP PUBLIC KEY BLOCK-----