Skip to content

Commit 6c438e4

Browse files
committed
Work toward payments processing via crypto_licensing
1 parent 90d97ca commit 6c438e4

File tree

11 files changed

+503
-95
lines changed

11 files changed

+503
-95
lines changed

dkim-setup renamed to DKIM-setup

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
# and we do not want people using the same email address, or other people's
6767
# email addresses.
6868

69-
KTYPE="rsa" # "ed25519" # but not well supported yet; even by Cloudflare
69+
KTYPE="ed25519" # "rsa" # Ed25519 is not well supported yet; even by Cloudflare?
7070

7171
COMPANY=""
7272
while [ "${COMPANY}" == "" ]; do

GNUmakefile

Lines changed: 174 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -147,23 +147,168 @@ deps: $(TXT) slip39/gui/SLIP-39.txt slip39/layout/COVER.txt
147147
# Agent Keypairs, Product Licences
148148
#
149149

150-
GLOBAL_OPTIONS = -vv
150+
# The SLIP-39 App is owned by Perry Kundert
151+
#
152+
# Dominion R&D Corp sub-licenses its crypto-licensing module and licensing server,
153+
# and also owns the master license for PySimpleGUI, which it provisions as a Distribution
154+
# Key for Perry's SLIP-39.App to use.
155+
#
156+
#
157+
158+
GLOBAL_OPTIONS = -v
151159

152160
CREDENTIALS = $(abspath $(HOME)/.crypto-licensing )
153161

162+
# The Dominion R&D Corp. root signing keypair. Used to issue Licenses for general Dominion
163+
# products and services.
164+
DOMINION-AUTH = "Dominion R&D Corp."
165+
DOMINION-USER = "[email protected]"
166+
DOMINION-DOMN = "dominionrnd.com"
167+
DOMINION-NAME = "dominion"
168+
DOMINION-SERV = "dominion"
169+
DOMINION-PROD = "Dominion"
170+
DOMINION-KEY = $(CREDENTIALS)/dominion.crypto-keypair
171+
172+
# Dominion R&D Corp.'s signing keypair for crypto-licensing related products.
173+
DOMINION-LIC-AUTH= "Dominion R&D Corp. (Licensing)"
174+
DOMINION-LIC-USER= "[email protected]"
175+
DOMINION-LIC-DOMN= "dominionrnd.com"
176+
DOMINION-LIC-NAME= "crypto-licensing"
177+
DOMINION-LIC-SERV= "crypto-licensing"
178+
DOMINION-LIC-PROD= "Crypto Licensing"
179+
DOMINION-LIC-KEY= $(CREDENTIALS)/crypto-licensing.crypto-keypair
180+
DOMINION-LIC-LIC= $(CREDENTIALS)/crypto-licensing.crypto-license
181+
182+
PERRY-K-AUTH = "Perry Kundert"
183+
PERRY-K-USER = "[email protected]"
184+
PERRY-K-DOMN = "perry.kundert.ca"
185+
PERRY-K-NAME = "perry-kundert"
186+
PERRY-K-SERV = "perry-kundert"
187+
PERRY-K-PROD = "Perry Kundert"
188+
PERRY-K-KEY = $(CREDENTIALS)/perry-kundert.crypto-keypair
189+
PERRY-K-LIC = $(CREDENTIALS)/perry-kundert.crypto-license
190+
191+
# An Authoring keypair is created for Perry Kundert's SLIP-39, and a License for the SLIP-39 App
192+
SLIP-39-AUTH = "Perry Kundert (SLIP-39)"
193+
SLIP-39-USER = "[email protected]"
194+
SLIP-39-DOMN = "slip39.com"
195+
SLIP-39-NAME = "slip-39-app"
196+
SLIP-39-SERV = "slip-39-app"
197+
SLIP-39-PROD = "SLIP-39 App"
198+
SLIP-39-KEY = $(CREDENTIALS)/slip-39-app.crypto-keypair
199+
SLIP-39-LIC = $(CREDENTIALS)/slip-39-app.crypto-license
200+
201+
# The root Dominion authoring key is used for issuing the SLIP-39 GUI grants
202+
SLIP-39-GUI-AUTH= "Dominion R&D Corp. (PySimpleGUI)"
203+
SLIP-39-GUI-USER= $(DOMINION-USER)
204+
SLIP-39-GUI-DOMN= $(DOMINION-DOMN)
205+
SLIP-39-GUI-NAME= $(DOMINION-NAME)
206+
SLIP-39-GUI-SERV= $(DOMINION-SERV)
207+
SLIP-39-GUI-PROD= "SLIP-39 PySimpleGUI"
208+
SLIP-39-GUI-KEY = $(CREDENTIALS)/slip-39-pysimplegui.crypto-keypair
209+
SLIP-39-GUI-LIC = $(CREDENTIALS)/slip-39-pysimplegui.crypto-license
210+
211+
# The Dominion R&D Corp. crypto-licensing authoring keypair is used for .
212+
SLIP-39-LIC-AUTH= $(DOMINION-LIC-AUTH)
213+
SLIP-39-LIC-USER= $(DOMINION-LIC-USER)
214+
SLIP-39-LIC-DOMN= $(DOMINION-LIC-DOMN)
215+
SLIP-39-LIC-NAME= $(DOMINION-LIC-NAME)
216+
SLIP-39-LIC-SERV= $(DOMINION-LIC-SERV)
217+
SLIP-39-LIC-PROD= "SLIP-39 Licensing"
218+
SLIP-39-LIC-KEY = $(CREDENTIALS)/slip-39-licensing.crypto-keypair
219+
SLIP-39-LIC-LIC = $(CREDENTIALS)/slip-39-licensing.crypto-license
220+
221+
PAY-TEST-LIC = slip39/invoice/payments_test/perry-kundert.crypto-license
222+
154223
export CRYPTO_LIC_PASSWORD
155224
export CRYPTO_LIC_USERNAME
156225

157-
.PHONY: slip-39 perry-kundert
158-
products: slip-39 \
159-
perry-kundert \
160-
161-
slip-39:
162-
163-
perry-kundert: [email protected]
164-
perry-kundert: CRYPTO_LIC_PASSWORD=password
165-
perry-kundert: slip39/invoice/payments_test/perry-kundert.crypto-license
166-
perry-kundert: GRANTS="{\"crypto-licensing-server\": {\
226+
.PHONY: licenses # perry-kundert
227+
licenses: $(SLIP-39-LIC) # perry-kundert
228+
229+
230+
# The slip-39 Keypair and License is signed and issued by Perry Kundert, who is the client for the
231+
# various license dependencies (slip-39-pysimplegui, slip-39-licensing) issued by Dominion R&D
232+
# Corp. to Perry for his SLIP-39.App. The base slip-39-app.crypto-license shipped for free with the
233+
# SLIP-39.App authorizes the basic tier of operation for the SLIP-39.App. Other licenses may be
234+
# issued to specific client's Ed25519 keypair Public Key, a specific Machine ID or their user name.
235+
236+
$(SLIP-39-KEY): AUTHOR=$(SLIP-39-AUTH)
237+
$(SLIP-39-KEY): KEYNAME=$(SLIP-39-NAME)
238+
$(SLIP-39-KEY): [email protected]
239+
$(SLIP-39-KEY): CRYPTO_LIC_PASSWORD=$(shell cat $(CREDENTIALS)/slip-39.crypto-password || echo -)
240+
241+
242+
$(PERRY-K-KEY): AUTHOR=$(PERRY-K-AUTH)
243+
$(PERRY-K-KEY): KEYNAME=$(PERRY-K-NAME)
244+
$(PERRY-K-KEY): USERNAME=$(PERRY-K-USER)
245+
$(PERRY-K-KEY): CRYPTO_LIC_PASSWORD=$(shell cat $(basename $@).crypto-password || echo - )
246+
247+
$(PERRY-K-LIC): AUTHOR=$(PERRY-K-AUTH)
248+
$(PERRY-K-LIC): KEYNAME=$(PERRY-K-NAME)
249+
$(PERRY-K-LIC): USERNAME=$(PERRY-K-USER)
250+
$(PERRY-K-LIC): DOMAIN=$(PERRY-K-DOMN)
251+
$(PERRY-K-LIC): PRODUCT=$(PERRY-K-PROD)
252+
$(PERRY-K-LIC): SERVICE=$(PERRY-K-SERV)
253+
$(PERRY-K-LIC): GRANTS=$(shell cat $(basename $@).grants )
254+
$(PERRY-K-LIC): LICENSE_OPTIONS=
255+
$(PERRY-K-LIC): CRYPTO_LIC_PASSWORD=$(shell cat $(basename $@).crypto-password || echo - )
256+
257+
258+
# The base SLIP-39 License is generic; isn't issued to a specific client, so can be sub-licensed by
259+
# any end-user using their Ed25519 private key.
260+
$(SLIP-39-LIC): AUTHOR=$(SLIP-39-AUTH)
261+
$(SLIP-39-LIC): KEYNAME=$(SLIP-39-NAME)
262+
$(SLIP-39-LIC): USERNAME=$(SLIP-39-USER)
263+
$(SLIP-39-LIC): DOMAIN=$(SLIP-39-DOMN)
264+
$(SLIP-39-LIC): PRODUCT=$(SLIP-39-PROD) # license: slip-39
265+
$(SLIP-39-LIC): SERVICE=$(SLIP-39-SERV) # service: slip-39
266+
$(SLIP-39-LIC): GRANTS=$(shell cat $(basename $@).grants )
267+
$(SLIP-39-LIC): CRYPTO_LIC_PASSWORD=$(shell cat $(basename $@).crypto-password || echo - )
268+
$(SLIP-39-LIC): LICENSE_OPTIONS=--dependency $(PERRY-K-LIC) --dependency $(SLIP-39-GUI-LIC) --dependency $(DOMINION-LIC-LIC)
269+
$(SLIP-39-LIC): $(PERRY-K-LIC) $(SLIP-39-GUI-LIC) $(DOMINION-LIC-LIC)
270+
271+
# The SLIP-39 GUI sub-License is signed by Dominion R&D Corp.'s Root authoring keypair, and issued
272+
# to the Perry Kundert (SLIP-39) client public key.
273+
274+
$(SLIP-39-GUI-KEY): $(DOMINION-KEY)
275+
ln -fs $< $@
276+
ln -fs $(basename $<).crypto-password $(basename $@).crypto-password
277+
278+
$(SLIP-39-GUI-LIC): AUTHOR=$(SLIP-39-GUI-AUTH)
279+
$(SLIP-39-GUI-LIC): KEYNAME=$(SLIP-39-GUI-NAME)
280+
$(SLIP-39-GUI-LIC): USERNAME=$(SLIP-39-GUI-USER)
281+
$(SLIP-39-GUI-LIC): DOMAIN=$(SLIP-39-GUI-DOMN)
282+
$(SLIP-39-GUI-LIC): PRODUCT=$(SLIP-39-GUI-PROD) # ==> license: slip-39-pysimplegui
283+
$(SLIP-39-GUI-LIC): SERVICE=$(SLIP-39-GUI-SERV) # ==> service: dominion
284+
$(SLIP-39-GUI-LIC): GRANTS=$(shell cat $(basename $@).grants )
285+
$(SLIP-39-GUI-LIC): CRYPTO_LIC_PASSWORD=$(shell cat $(basename $@).crypto-password || echo - )
286+
$(SLIP-39-GUI-LIC): LICENSE_OPTIONS=--client $(SLIP-39-AUTH) --client-pubkey $(shell jq '.vk' < $(SLIP-39-KEY) )
287+
288+
289+
# The SLIP-39 Licensing sub-License is signed by Dominion R&D Corp.'s Crypto-Licensing authoring
290+
# keypair, and issued to Perry Kundert (SLIP-39) client public key.
291+
292+
$(SLIP-39-LIC-KEY): $(DOMINION-LIC-KEY)
293+
ln -fs $< $@
294+
ln -fs $(basename $<).crypto-password $(basename $@).crypto-password
295+
296+
$(SLIP-39-LIC-LIC): AUTHOR=$(SLIP-39-LIC-AUTH)
297+
$(SLIP-39-LIC-LIC): KEYNAME=$(SLIP-39-LIC-NAME)
298+
$(SLIP-39-LIC-LIC): USERNAME=$(SLIP-39-LIC-USER)
299+
$(SLIP-39-LIC-LIC): DOMAIN=$(SLIP-39-LIC-DOMN)
300+
$(SLIP-39-LIC-LIC): PRODUCT=$(SLIP-39-LIC-PROD) # ==> license: slip-39-licensing
301+
$(SLIP-39-LIC-LIC): SERVICE=$(SLIP-39-LIC-SERV) # ==> service: crypto-licensing
302+
$(SLIP-39-LIC-LIC): GRANTS=$(shell cat $(basename $@).grants )
303+
$(SLIP-39-LIC-LIC): CRYPTO_LIC_PASSWORD=$(shell cat $(basename $@).crypto-password || echo - )
304+
$(SLIP-39-LIC-LIC): LICENSE_OPTIONS=--dependency $(CREDENTIALS)/crypto-licensing.crypto-license --client $(SLIP-39-AUTH) --client-pubkey $(shell jq '.vk' < $(SLIP-39-KEY))
305+
306+
307+
308+
$(PAY-TEST-LIC): GLOBAL_OPTIONS=$(GLOBAL_OPTIONS) --reverse-save --no-registering
309+
$(PAY-TEST-LIC): [email protected]
310+
$(PAY-TEST-LIC): CRYPTO_LIC_PASSWORD=password
311+
$(PAY-TEST-LIC): GRANTS="{\"crypto-licensing-server\": {\
167312
\"override\": { \
168313
\"rate\": \"0.1%\", \
169314
\"crypto\": { \
@@ -175,28 +320,29 @@ perry-kundert: GRANTS="{\"crypto-licensing-server\": {\
175320

176321

177322

323+
# Preserve all "secondary" intermediate files (eg. the .crypto-keypair generated)
324+
.SECONDARY:
325+
178326
# Create .crypto-keypair from seed; note: if the make rule fails, intermediate files are deleted.
179327
# We expect any password to be transmitted in CRYPTO_LIC_PASSWORD env. var.
180328
%.crypto-keypair: %.crypto-seed
181329
$(PY3) -m crypto_licensing $(GLOBAL_OPTIONS) \
182-
--extra $(dir $(basename $@ )) \
183-
--name $(notdir $(basename $@ )) \
184-
--reverse-save \
330+
--name $(KEYNAME) \
331+
--extra $(dir $(basename $@ )) --reverse-save \
185332
registered \
186333
--username $(USERNAME) \
187-
--seed $$( cat $< )
334+
--seed "$$( cat $< || true )"
188335

189336
# Create .crypto-license, signed by .crypto-keypair
190337
%.crypto-license : %.crypto-keypair
191338
$(PY3) -m crypto_licensing $(GLOBAL_OPTIONS) \
192-
--extra $(dir $(basename $@ )) \
193-
--name $(notdir $(basename $@ )) \
194-
--reverse-save \
339+
--name $(KEYNAME) \
340+
--extra $(dir $(basename $@ )) --reverse-save \
195341
license \
196342
--username $(USERNAME) --no-registering \
197-
--client $(CLIENT) --client-pubkey $(CLIENT_PUBKEY) \
198-
--grant $(GRANTS) \
199-
--author $(AUTHOR) --domain $(DOMAIN) --product $(PRODUCT) $(LICENSE_OPTIONS)
343+
--grant '$(GRANTS)' \
344+
--author $(AUTHOR) --domain $(DOMAIN) \
345+
--service $(SERVICE) --product $(PRODUCT) $(LICENSE_OPTIONS)
200346

201347

202348
#
@@ -738,13 +884,18 @@ upload: upload-check wheel
738884
clean:
739885
@rm -rf MANIFEST *.png build dist auto *.egg-info $(shell find . -name '__pycache__' )
740886

887+
.PHONY: deps-test
888+
deps-test: slip39/payments_test/slip-39-app.crypto-license
889+
890+
slip39/payments_test/slip-39-app.crypto-license: $(SLIP-39-LIC)
891+
cp $< $@
741892

742893
# Run only tests with a prefix containing the target string, eg test-api
743-
test-%:
894+
test-%: deps-test
744895
$(PY3TEST) $(shell find slip39 -name '*$**_test.py')
745896

746897
# Run all tests with names matching the target string
747-
unit-%:
898+
unit-%: deps-test
748899
$(PY3TEST) -k $*
749900

750901
nix-%:

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
base58 >=2.0.1,<3
22
chacha20poly1305 >=0.0.3
33
click >=8.1.3,<9
4-
crypto-licensing >=5.0.0,<6
4+
crypto-licensing >=5.1.4,<6
55
cx_Freeze >=6.12 ; sys_platform == "win32"
66
fpdf2 >=2.7.6,<3
77
#hdwallet >=2.3.0,<3

slip39/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@
2626
from .api import * # noqa F403
2727
from .layout import * # noqa F403
2828
from .recovery import * # noqa F403
29+
from .limits import * # noqa F403

slip39/gui/main.py

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,14 @@
2525
import pprint
2626
import re
2727
import sys
28-
import subprocess
2928

3029
from itertools import islice
3130

3231
import PySimpleGUI as sg
3332

3433
from ..api import Account, create, group_parser, random_secret, cryptopaths_parser, paper_wallet_available, stretch_seed_entropy
3534
from ..recovery import recover, recover_bip39, produce_bip39, scan_entropy, display_entropy
36-
from ..util import log_level, log_cfg, ordinal, commas, chunker, hue_shift, rate_dB, entropy_rating_dB, timing, avg, parse_scutil
35+
from ..util import log_level, log_cfg, ordinal, commas, chunker, hue_shift, rate_dB, entropy_rating_dB, timing, avg, user_name_full
3736
from ..layout import write_pdfs, printers_available
3837
from ..defaults import (
3938
GROUPS, GROUP_THRESHOLD_RATIO, MNEM_PREFIX, CRYPTO_PATHS, BITS, BITS_BIP39, BITS_DEFAULT,
@@ -966,57 +965,6 @@ def update_seed_recovered( window, values, details, passphrase=None ):
966965
return f"Recovered Seed {recohex!r} doesn't match expected: {window['-SEED-'].get()!r}"
967966

968967

969-
def user_name_full():
970-
full_name = None
971-
if sys.platform == 'darwin':
972-
command = [ '/usr/sbin/scutil' ]
973-
command_input = "show State:/Users/ConsoleUser"
974-
elif sys.platform == 'win32':
975-
command = [ 'net', 'user', os.environ['USERNAME'] ]
976-
command_input = None
977-
else: # assume *nix
978-
command = [ 'getent', 'passwd', os.environ['USER'] ]
979-
command_input = None
980-
981-
subproc = subprocess.run(
982-
command,
983-
input = command_input,
984-
capture_output = True,
985-
encoding = 'UTF-8',
986-
)
987-
assert subproc.returncode == 0 and subproc.stdout, \
988-
f"{' '.join( command )!r} command failed, or no output returned"
989-
990-
if sys.platform == 'darwin':
991-
scutil = parse_scutil( subproc.stdout )
992-
if uid := scutil.get( 'UID' ):
993-
for session in scutil.get( 'SessionInfo', {} ).values():
994-
if session.get( 'kCGSSessionUserIDKey' ) == uid:
995-
# eg.: " kCGSessionLongUserNameKey : Perry Kundert"
996-
full_name = session.get( 'kCGSessionLongUserNameKey' )
997-
break
998-
elif sys.platform == 'win32':
999-
for li in subproc.stdout.split( '\n' ):
1000-
if li.startswith( 'Full Name' ):
1001-
# eg.: "Full Name IEUser"
1002-
full_name = li[9:].strip()
1003-
break
1004-
else:
1005-
# getent="perry:x:1002:1004:Perry Kundert,,,:/home/perry:/bin/bash"
1006-
# >>> getent.split(':')
1007-
# ['perry', 'x', '1002', '1004', 'Perry Kundert,,,', '/home/perry', '/bin/bash']
1008-
pwents = subproc.stdout.split( ':' )
1009-
assert len( pwents ) > 4, \
1010-
f"Unrecognized passwd entry: {li}"
1011-
gecos = pwents[4]
1012-
full_name = gecos.split( ',' )[0] # Discard ...,building,room,phone,...
1013-
1014-
assert full_name, \
1015-
"User's full name not found"
1016-
log.info( f"Current user's full name: {full_name!r}" )
1017-
return full_name
1018-
1019-
1020968
def app(
1021969
names = None,
1022970
group = None,
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@
1717
from __future__ import annotations
1818

1919
import logging
20-
import traceback
2120
import sys
21+
import traceback
2222

2323
from typing import Optional
2424
from pathlib import Path
2525
from enum import Enum
2626

27-
import crypto_licensing
2827
from crypto_licensing import licensing
2928
from crypto_licensing.misc import deduce_name
3029

@@ -178,7 +177,8 @@ def reload(
178177
caller, which may be supplied via <generator>.send( ... ).
179178
180179
If an error occurs (such as no Grants found), a (Process.ERROR, <str>) will be produced. This
181-
will often be
180+
will often be the signal that additional Licenses are required (or just that the wrong
181+
credentials were provided).
182182
183183
"""
184184
# If no username/password provided, we'll loop once w/ None, then request input for subsequent authorizations
@@ -299,7 +299,7 @@ def reload(
299299
except Exception as exc:
300300
log.error( "Failed loading Agent Keypair and/or License: {exc}".format(
301301
exc=''.join( traceback.format_exception( *sys.exc_info() )) if log.isEnabledFor( logging.TRACE ) else exc ))
302-
with open( Path( crypto_licensing.__file__ ).resolve().parent / 'licensing' / 'static' / 'txt' / 'CL-KEYPAIR-MISSING.txt', 'r' ) as f:
302+
with open( Path( licensing.__file__ ).resolve().parent / 'static' / 'txt' / 'CL-KEYPAIR-MISSING.txt', 'r' ) as f:
303303
error = f.read().format(
304304
DISTRIBUTION = deduce_name( basename=basename, filename=kwds.get( 'filename' ), package=kwds.get( 'package' ), default=client and client.servicekey or "" ),
305305
KEYPATTERN = licensing.KEYPATTERN,

0 commit comments

Comments
 (0)