├── .dockerignore ├── .github └── workflows │ ├── linter.yml │ ├── linux.yml │ └── macOS.yml ├── .gitignore ├── .gitmodules ├── .vscode ├── c_cpp_properties.json ├── launch.json ├── settings.json └── tasks.json ├── CLA-signed ├── CLA.gorazdko.41F0EA1699A74C1E2FA41B538CF96BC3FF9DBBCE.asc ├── CLA.secinthenet.4da78f8447e15659ab7e06db0409549979ff5b43.asc └── CLA.wolfmcnally.943652EE38441760C3DC35364B6C2FCF894780AE.asc ├── CLA.md ├── CODEOWNERS ├── CONTRIBUTING.md ├── Dockerfile ├── Docs ├── Install-Windows.md ├── MANUAL.md └── Usage.md ├── LICENSE ├── Makefile.in ├── README.md ├── bootstrap.sh ├── build-aux ├── config.guess ├── config.sub └── install-sh ├── build.sh ├── build ├── build-tailsOS.Dockerfile └── packaging.md ├── configure ├── configure.ac ├── debian ├── README.Debian ├── README.source ├── changelog ├── clean ├── control ├── copyright ├── manpage.1.ex ├── manpage.md.ex ├── manpage.sgml.ex ├── manpage.xml.ex ├── patches │ ├── fix-build.diff │ └── series ├── postinst.ex ├── postrm.ex ├── preinst.ex ├── prerm.ex ├── rules ├── salsa-ci.yml.ex ├── seedtool-cli-docs.docs ├── seedtool-cli.cron.d.ex ├── seedtool-cli.doc-base.ex ├── source │ ├── format │ ├── include-binaries │ └── options ├── upstream │ └── metadata.ex └── watch.ex ├── example-scripts ├── bip39-to-sskr.sh └── sskr-to-bip39.sh ├── images └── logos │ ├── README.md │ ├── seedtool-logo-black.jpg │ ├── seedtool-logo-black.png │ ├── seedtool-logo-black.psd │ ├── seedtool-logo-shapes.ai │ ├── seedtool-logo-white.jpg │ ├── seedtool-logo-white.png │ ├── seedtool-logo-white.psd │ ├── seedtool-screen.jpg │ ├── seedtool-screen.png │ └── seedtool-screen.psd ├── install-sh ├── manual-images └── seedqrcode.png ├── set_build_paths.sh └── src ├── .gitignore ├── Makefile.in ├── cbor-utils.hpp ├── config.h.in ├── format-base10.cpp ├── format-base10.hpp ├── format-base6.cpp ├── format-base6.hpp ├── format-bip39.cpp ├── format-bip39.hpp ├── format-bits.cpp ├── format-bits.hpp ├── format-bytewords-minimal.cpp ├── format-bytewords-minimal.hpp ├── format-bytewords-uri.cpp ├── format-bytewords-uri.hpp ├── format-bytewords.cpp ├── format-bytewords.hpp ├── format-cards.cpp ├── format-cards.hpp ├── format-dice.cpp ├── format-dice.hpp ├── format-hex.cpp ├── format-hex.hpp ├── format-ints.cpp ├── format-ints.hpp ├── format-random.cpp ├── format-random.hpp ├── format-sskr.cpp ├── format-sskr.hpp ├── format.cpp ├── format.hpp ├── formats-all.hpp ├── hkdf.c ├── hkdf.h ├── params.cpp ├── params.hpp ├── random.cpp ├── random.hpp ├── randombytes.c ├── randombytes.h ├── seedtool.cpp ├── test.sh ├── utils.cpp └── utils.hpp /.dockerignore: -------------------------------------------------------------------------------- 1 | # Exclude docker related files so that the docker layer cache won't be 2 | # invalidated when editing them because the build context changes. 3 | Dockerfile 4 | .dockerignore 5 | 6 | # Created by https://www.gitignore.io/api/macos 7 | 8 | ### macOS ### 9 | # General 10 | .DS_Store 11 | .AppleDouble 12 | .LSOverride 13 | 14 | # Icon must end with two \r 15 | Icon 16 | 17 | # Thumbnails 18 | ._* 19 | 20 | # Files that might appear in the root of a volume 21 | .DocumentRevisions-V100 22 | .fseventsd 23 | .Spotlight-V100 24 | .TemporaryItems 25 | .Trashes 26 | .VolumeIcon.icns 27 | .com.apple.timemachine.donotpresent 28 | 29 | # Directories potentially created on remote AFP share 30 | .AppleDB 31 | .AppleDesktop 32 | Network Trash Folder 33 | Temporary Items 34 | .apdisk 35 | 36 | # End of https://www.gitignore.io/api/macos 37 | 38 | # Created by https://www.gitignore.io/api/c 39 | 40 | ### C ### 41 | # Prerequisites 42 | *.d 43 | 44 | # Object files 45 | *.o 46 | *.ko 47 | *.obj 48 | *.elf 49 | 50 | # Linker output 51 | *.ilk 52 | *.map 53 | *.exp 54 | 55 | # Precompiled Headers 56 | *.gch 57 | *.pch 58 | 59 | # Libraries 60 | *.lib 61 | *.a 62 | *.la 63 | *.lo 64 | 65 | # Shared objects (inc. Windows DLLs) 66 | *.dll 67 | *.so 68 | *.so.* 69 | *.dylib 70 | 71 | # Executables 72 | *.exe 73 | *.out 74 | *.app 75 | *.i*86 76 | *.x86_64 77 | *.hex 78 | 79 | # Debug files 80 | *.dSYM/ 81 | *.su 82 | *.idb 83 | *.pdb 84 | 85 | # Kernel Module Compile Results 86 | *.mod* 87 | *.cmd 88 | .tmp_versions/ 89 | modules.order 90 | Module.symvers 91 | Mkfile.old 92 | dkms.conf 93 | 94 | # End of https://www.gitignore.io/api/c 95 | 96 | autom4te.cache 97 | autoscan.log 98 | Makefile 99 | config.log 100 | config.status 101 | configure.scan 102 | config.h 103 | sysroot/ 104 | -------------------------------------------------------------------------------- /.github/workflows/linter.yml: -------------------------------------------------------------------------------- 1 | name: linter 2 | on: [push, pull_request] 3 | jobs: 4 | Lint: 5 | runs-on: macos-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - run: brew install cppcheck 9 | - run: cppcheck --enable=all --error-exitcode=1 --inline-suppr --suppress=missingInclude --suppress=ConfigurationNotChecked . 10 | -------------------------------------------------------------------------------- /.github/workflows/linux.yml: -------------------------------------------------------------------------------- 1 | name: linux 2 | on: [push, pull_request] 3 | jobs: 4 | build-Linux: 5 | runs-on: ubuntu-18.04 6 | steps: 7 | - uses: actions/checkout@v2 8 | - run: wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - || exit 1 9 | - run: sudo apt-add-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main" || exit 1 10 | - run: sudo apt-get update || exit 1 11 | - run: sudo apt-get install -y clang-10 libc++-10-dev libc++abi-10-dev shunit2 make || exit 1 12 | - run: export CC="clang-10" && export CXX="clang++-10" && ./build.sh 13 | - run: sudo make install 14 | - run: make distclean 15 | -------------------------------------------------------------------------------- /.github/workflows/macOS.yml: -------------------------------------------------------------------------------- 1 | name: macOS 2 | on: [push, pull_request] 3 | jobs: 4 | build-MacOS: 5 | runs-on: macos-latest 6 | steps: 7 | - uses: actions/checkout@v2 8 | - run: brew install autoconf automake libtool shunit2 cppcheck 9 | - run: ./build.sh 10 | - run: sudo make install 11 | - run: make distclean 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/macos 2 | 3 | ### macOS ### 4 | # General 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | 9 | # Icon must end with two \r 10 | Icon 11 | 12 | # Thumbnails 13 | ._* 14 | 15 | # Files that might appear in the root of a volume 16 | .DocumentRevisions-V100 17 | .fseventsd 18 | .Spotlight-V100 19 | .TemporaryItems 20 | .Trashes 21 | .VolumeIcon.icns 22 | .com.apple.timemachine.donotpresent 23 | 24 | # Directories potentially created on remote AFP share 25 | .AppleDB 26 | .AppleDesktop 27 | Network Trash Folder 28 | Temporary Items 29 | .apdisk 30 | 31 | # End of https://www.gitignore.io/api/macos 32 | 33 | # Created by https://www.gitignore.io/api/c 34 | 35 | ### C ### 36 | # Prerequisites 37 | *.d 38 | 39 | # Object files 40 | *.o 41 | *.ko 42 | *.obj 43 | *.elf 44 | 45 | # Linker output 46 | *.ilk 47 | *.map 48 | *.exp 49 | 50 | # Precompiled Headers 51 | *.gch 52 | *.pch 53 | 54 | # Libraries 55 | *.lib 56 | *.a 57 | *.la 58 | *.lo 59 | 60 | # Shared objects (inc. Windows DLLs) 61 | *.dll 62 | *.so 63 | *.so.* 64 | *.dylib 65 | 66 | # Executables 67 | *.exe 68 | *.out 69 | *.app 70 | *.i*86 71 | *.x86_64 72 | *.hex 73 | 74 | # Debug files 75 | *.dSYM/ 76 | *.su 77 | *.idb 78 | *.pdb 79 | 80 | # Kernel Module Compile Results 81 | *.mod* 82 | *.cmd 83 | .tmp_versions/ 84 | modules.order 85 | Module.symvers 86 | Mkfile.old 87 | dkms.conf 88 | 89 | # End of https://www.gitignore.io/api/c 90 | 91 | autom4te.cache 92 | autoscan.log 93 | Makefile 94 | config.log 95 | config.status 96 | configure.scan 97 | config.h 98 | sysroot/ 99 | .vscode/configurationCache.log 100 | .vscode/dryrun.log 101 | .vscode/targets.log 102 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "deps/bc-crypto-base"] 2 | path = deps/bc-crypto-base 3 | url = https://github.com/BlockchainCommons/bc-crypto-base.git 4 | [submodule "deps/bc-shamir"] 5 | path = deps/bc-shamir 6 | url = https://github.com/blockchaincommons/bc-shamir.git 7 | [submodule "deps/bc-bip39"] 8 | path = deps/bc-bip39 9 | url = https://github.com/blockchaincommons/bc-bip39.git 10 | [submodule "deps/argp-standalone"] 11 | path = deps/argp-standalone 12 | url = https://github.com/BlockchainCommons/argp-standalone.git 13 | ignore = dirty 14 | [submodule "deps/bc-ur"] 15 | path = deps/bc-ur 16 | url = https://github.com/BlockchainCommons/bc-ur.git 17 | [submodule "deps/bc-sskr"] 18 | path = deps/bc-sskr 19 | url = https://github.com/BlockchainCommons/bc-sskr.git 20 | [submodule "deps/shunit2"] 21 | path = deps/shunit2 22 | url = https://github.com/kward/shunit2 23 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Mac", 5 | "includePath": [ 6 | "${workspaceFolder}/**" 7 | ], 8 | "defines": [], 9 | "macFrameworkPath": [ 10 | "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks" 11 | ], 12 | "compilerPath": "/usr/bin/clang", 13 | "cStandard": "c11", 14 | "intelliSenseMode": "clang-x64" 15 | } 16 | ], 17 | "version": 4 18 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | // You may need to install the extension "CodeLLDB" for debugging to work on Macs with Catalina. 6 | "name": "Build and Debug", 7 | "type": "lldb", 8 | "request": "launch", 9 | "program": "${workspaceFolder}/src/seedtool", 10 | "args": [ ], 11 | "cwd": "${workspaceFolder}/src", 12 | "preLaunchTask": "Build" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "Makefile.in": "makefile" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Configure", 6 | "type": "shell", 7 | "command": "source set_build_paths.sh && ./configure", 8 | "problemMatcher": [] 9 | }, 10 | { 11 | "label": "Build", 12 | "type": "shell", 13 | "command": "source set_build_paths.sh && make all && dsymutil src/seedtool", 14 | "problemMatcher": { "base": "$gcc", "fileLocation": ["relative", "${workspaceRoot}/src"] }, 15 | "group": { 16 | "kind": "build", 17 | "isDefault": true 18 | } 19 | }, 20 | { 21 | "label": "Test", 22 | "type": "shell", 23 | "command": "source set_build_paths.sh && make check", 24 | "problemMatcher": { "base": "$gcc", "fileLocation": ["relative", "${workspaceRoot}/src"] }, 25 | "group": { 26 | "kind": "test", 27 | "isDefault": true 28 | } 29 | }, 30 | { 31 | "label": "Distribution Test", 32 | "type": "shell", 33 | "command": "source set_build_paths.sh && make distcheck", 34 | "problemMatcher": { "base": "$gcc", "fileLocation": ["relative", "${workspaceRoot}/src"] }, 35 | "group": "test" 36 | }, 37 | { 38 | "label": "Distribution", 39 | "type": "shell", 40 | "command": "source set_build_paths.sh && make dist", 41 | "problemMatcher": { "base": "$gcc", "fileLocation": ["relative", "${workspaceRoot}/src"] } 42 | }, 43 | { 44 | "label": "Distribution Clean", 45 | "type": "shell", 46 | "command": "source set_build_paths.sh && make distclean", 47 | "problemMatcher": [] 48 | }, 49 | { 50 | "label": "Distribution Build", 51 | "type": "shell", 52 | "command": "source set_build_paths.sh && ./build.sh", 53 | "problemMatcher": [] 54 | }, 55 | { 56 | "label": "Clean", 57 | "type": "shell", 58 | "command": "source set_build_paths.sh && make clean", 59 | "problemMatcher": [] 60 | }, 61 | { 62 | "label": "Install", 63 | "type": "shell", 64 | "command": "sudo make install", 65 | "problemMatcher": { "base": "$gcc", "fileLocation": ["relative", "${workspaceRoot}/src"] } 66 | }, 67 | { 68 | "label": "Uninstall", 69 | "type": "shell", 70 | "command": "sudo make uninstall", 71 | "problemMatcher": { "base": "$gcc", "fileLocation": ["relative", "${workspaceRoot}/src"] } 72 | }, 73 | { 74 | "label": "Lint", 75 | "type": "shell", 76 | "command": "make lint", 77 | "problemMatcher": { 78 | "fileLocation": ["relative", "${workspaceRoot}/src"], 79 | "severity": "warning", 80 | "pattern": { 81 | "regexp": "^(.*?):(\\d+):(\\d+):\\s+(error|warning|style|performance|portability|note|information):(.*)$", 82 | "file": 1, 83 | "line": 2, 84 | "column": 3, 85 | "severity": 4, 86 | "message": 5 87 | } 88 | } 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /CLA-signed/CLA.gorazdko.41F0EA1699A74C1E2FA41B538CF96BC3FF9DBBCE.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNED MESSAGE----- 2 | Hash: SHA512 3 | 4 | # Contributor License Agreement 5 | 6 | Version 1.0 7 | 8 | Name: Gorazd Kovacic 9 | 10 | E-Mail: gorazdko@gmail.com 11 | 12 | Legal Jurisdiction: Wyoming, United States of America 13 | 14 | Project: https://github.com/BlockchainCommons/bc-seedtool-cli 15 | 16 | Date: 09-03-2020 17 | 18 | ## Purpose 19 | 20 | This agreement gives Blockchain Commons, LLC the permission it needs in order to accept my contributions into its open software project and to manage the intellectual property in that project over time. 21 | 22 | ## License 23 | 24 | I hereby license Blockchain Commons, LLC to: 25 | 26 | 1. do anything with my contributions that would otherwise infringe my copyright in them 27 | 28 | 2. do anything with my contributions that would otherwise infringe patents that I can or become able to license 29 | 30 | 3. sublicense these rights to others on any terms they like 31 | 32 | ## Reliability 33 | 34 | I understand that Blockchain Commons will rely on this license. I may not revoke this license. 35 | 36 | ## Awareness 37 | 38 | I promise that I am familiar with legal rules, like ["work made for hire" rules](http://worksmadeforhire.com), that can give employers and clients ownership of intellectual property in work that I do. I am also aware that legal agreements I might sign, like confidential information and invention assignment agreements, will usually give ownership of intellectual property in my work to employers, clients, and companies that I found. If someone else owns intellectual property in my work, I need their permission to license it. 39 | 40 | ## Copyright Guarantee 41 | 42 | I promise not to offer contributions to the project that contain copyrighted work that I do not have legally binding permission to contribute under these terms. When I offer a contribution with permission, I promise to document in the contribution who owns copyright in what work, and how they gave permission to contribute it. If I later become aware that one of my contributions may have copyrighted work of others that I did not have permission to contribute, I will notify Blockchain Commons, in confidence, immediately. 43 | 44 | ## Patent Guarantee 45 | 46 | I promise not to offer contributions to the project that I know infringe patents of others that I do not have permission to contribute under these terms. 47 | 48 | ## Open Source Guarantee 49 | 50 | I promise not to offer contributions that contain or depend on the work of others, unless that work is available under a license that [Blue Oak Council rates bronze or better](https://blueoakconcil.org/list), such as the MIT License, two- or three-clause BSD License, the Apache License Version 2.0, or the Blue Oak Model License 1.0.0. When I offer a contribution containing or depending on others' work, I promise to document in the contribution who licenses that work, along with copies of their license terms. 51 | 52 | ## Disclaimers 53 | 54 | ***As far as the law allows, my contributions come as is, without any warranty or condition. Other than under [Copyright Guarantee](#copyright-guarantee), [Patent Guarantee](#patent-guarantee), or [Open Source Guarantee](#open-source-guarantee), I will not be liable to anyone for any damages related to my contributions or this contributor license agreement, under any kind of legal claim.*** 55 | 56 | - --- 57 | 58 | To sign this Contributor License Agreement, fill in `$name`, `$email`, and `$date` above. Then sign using GPG using the following command `gpg --armor --clearsign --output CLA.YOURGITHUBNAME.YOURGPGFINGERPRINT.asc CLA.md`, then either submit your signed Contributor License Agreement to this repo as a GPG signed Pull Request or email it to [ChristopherA@BlockchainCommons.com](mailto:ChristopherA@BlockchainCommons.com). 59 | 60 | -----BEGIN PGP SIGNATURE----- 61 | 62 | iQIzBAEBCgAdFiEEQfDqFpmnTB4vpBtTjPlrw/+du84FAmCQE4IACgkQjPlrw/+d 63 | u87qQA/9EHBvCPS9E2w29hBQVjEZTWBEJIaPRQCEU0THzwZ+Sf/06ND8Gcajw0mW 64 | EjCtgQ2zVPo8fvtqHjWBV+PMGpUAmMtW0r2LjOkC6MGNe5Re0q0QBlBhUf2BV8FH 65 | /LD5bJ3IJRZp8EEUKsLR2uDWRpcCr20DShInsvaXZBy8+ZZoFCjvqKbrkLOt7/xU 66 | 9hcyb3DIyRrHj/JddpmbSksA4LwJA2s4j8uzwRVf7DJxvKatH2M2RRATKYOhTxRo 67 | P/UW9JLVCHh8JunxFLikx2rZ+05qKNC1XqT8oUrnJFMqswWoBk+U7N3xdtl+imfg 68 | gi5ki6FiIjavwCRRmBAxyI2Y4emE92rEwCjF0FhP2wRGYyeOTuchM2dWMYtk8e/+ 69 | 9a6s2YuiTurQBpKiHQm98AC8VvEqCGnY9ellekNQAWhsVg5ALR73yeZReB0rolr/ 70 | qFKq/nIeBtigxqoSvHn4HeHNiwoFIx3w5KOhMKPk64j4GHglaK7qMBs3AG03rbVK 71 | rc7IhbkydCYiUDCAL3UKuxRtS+f6uEK378ounFIgxuo4ZCVb4EUijTv4E8q0foBZ 72 | TFj7IpQno+HkEqOSkzq30gCSsXxC/CorF42PJ5qm5jpYc9LtiaMKhc/WHkRc9SpH 73 | A1Xe/UBqgN5fITplHIAjLrYSYmj2NLctVGx5A2MmCbtrHz8B5jI= 74 | =xYXb 75 | -----END PGP SIGNATURE----- 76 | -------------------------------------------------------------------------------- /CLA-signed/CLA.secinthenet.4da78f8447e15659ab7e06db0409549979ff5b43.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNED MESSAGE----- 2 | Hash: SHA512 3 | 4 | # Contributor License Agreement 5 | 6 | Version 1.0 7 | 8 | Name: `Sylvia G` 9 | 10 | E-Mail: `q0h8xdveje@gmail.com` 11 | 12 | Legal Jurisdiction: Wyoming, United States of America 13 | 14 | Project: https://github.com/BlockchainCommons/bc-seedtool-cli 15 | 16 | Date: `March 31, 2021` 17 | 18 | ## Purpose 19 | 20 | This agreement gives Blockchain Commons, LLC the permission it needs in order to accept my contributions into its open software project and to manage the intellectual property in that project over time. 21 | 22 | ## License 23 | 24 | I hereby license Blockchain Commons, LLC to: 25 | 26 | 1. do anything with my contributions that would otherwise infringe my copyright in them 27 | 28 | 2. do anything with my contributions that would otherwise infringe patents that I can or become able to license 29 | 30 | 3. sublicense these rights to others on any terms they like 31 | 32 | ## Reliability 33 | 34 | I understand that Blockchain Commons will rely on this license. I may not revoke this license. 35 | 36 | ## Awareness 37 | 38 | I promise that I am familiar with legal rules, like ["work made for hire" rules](http://worksmadeforhire.com), that can give employers and clients ownership of intellectual property in work that I do. I am also aware that legal agreements I might sign, like confidential information and invention assignment agreements, will usually give ownership of intellectual property in my work to employers, clients, and companies that I found. If someone else owns intellectual property in my work, I need their permission to license it. 39 | 40 | ## Copyright Guarantee 41 | 42 | I promise not to offer contributions to the project that contain copyrighted work that I do not have legally binding permission to contribute under these terms. When I offer a contribution with permission, I promise to document in the contribution who owns copyright in what work, and how they gave permission to contribute it. If I later become aware that one of my contributions may have copyrighted work of others that I did not have permission to contribute, I will notify Blockchain Commons, in confidence, immediately. 43 | 44 | ## Patent Guarantee 45 | 46 | I promise not to offer contributions to the project that I know infringe patents of others that I do not have permission to contribute under these terms. 47 | 48 | ## Open Source Guarantee 49 | 50 | I promise not to offer contributions that contain or depend on the work of others, unless that work is available under a license that [Blue Oak Council rates bronze or better](https://blueoakconcil.org/list), such as the MIT License, two- or three-clause BSD License, the Apache License Version 2.0, or the Blue Oak Model License 1.0.0. When I offer a contribution containing or depending on others' work, I promise to document in the contribution who licenses that work, along with copies of their license terms. 51 | 52 | ## Disclaimers 53 | 54 | ***As far as the law allows, my contributions come as is, without any warranty or condition. Other than under [Copyright Guarantee](#copyright-guarantee), [Patent Guarantee](#patent-guarantee), or [Open Source Guarantee](#open-source-guarantee), I will not be liable to anyone for any damages related to my contributions or this contributor license agreement, under any kind of legal claim.*** 55 | 56 | - --- 57 | 58 | To sign this Contributor License Agreement, fill in `$name`, `$email`, and `$date` above. Then sign using GPG using the following command `gpg --armor --clearsign --output CLA.YOURGITHUBNAME.YOURGPGFINGERPRINT.asc CLA.md`, then either submit your signed Contributor License Agreement to this repo as a GPG signed Pull Request or email it to [ChristopherA@BlockchainCommons.com](mailto:ChristopherA@BlockchainCommons.com). 59 | 60 | -----BEGIN PGP SIGNATURE----- 61 | 62 | iQGzBAEBCgAdFiEETaePhEfhVlmrfgbbBAlUmXn/W0MFAmBkXvgACgkQBAlUmXn/ 63 | W0NjyQwAme1hxmXo4vEK5q8VZFxk8/Dqy43ZnQlSxFpFceoB12GJhpce1OxiHi7d 64 | LLErPnUV2AQAoo9L5qKTv0w3NRGsWur89s1EfSJCUtsqXPtqkzZS5GC47cAoEGxM 65 | cN0KIoJozIz2d0c7EFDy1p9bvb+r8H6FIkH/qNKSvuonLLaK+q0xgt6PUQcjY+NI 66 | CbiOjGiHBz4/BgYQOMa6E3knwM8WKQlRnhoL6JyjfVnD8QRkaus0NEFW/BBnw/cP 67 | GvlK61IdOaea1bGu68qmv45R6l9JilL7OKaY4tQnmTp3fMw/NYxnTpRIiW+kMXSn 68 | dOPNdeyk8UM6dJuLlxh9BstOhOER+UZ/zEAiim5vjYbBXzGMyP25gA9hkUXwX2a8 69 | Q0oocAoU+WwFqCHe7NyJeGieZhIFcBYNS2mdjsxfjjzWiz8huB407CN0+Kg0qLfQ 70 | 3VIUeFY70QTXPLwtci+eOI2sahGA0orYDjoC8/dpT/OyRhfT24kfH9U9UG39Mm5w 71 | mCm0wIUa 72 | =IUqj 73 | -----END PGP SIGNATURE----- 74 | -------------------------------------------------------------------------------- /CLA-signed/CLA.wolfmcnally.943652EE38441760C3DC35364B6C2FCF894780AE.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNED MESSAGE----- 2 | Hash: SHA256 3 | 4 | # Contributor License Agreement 5 | 6 | Version 1.0 7 | 8 | Name: `Wolf McNally` 9 | 10 | E-Mail: `wolf@wolfmcnally.com` 11 | 12 | Legal Jurisdiction: Wyoming, United States of America 13 | 14 | Project: https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli 15 | 16 | Date: `April 3, 2020` 17 | 18 | ## Purpose 19 | 20 | This agreement gives Blockchain Commons, LLC the permission it needs in order to accept my contributions into its open software project and to manage the intellectual property in that project over time. 21 | 22 | ## License 23 | 24 | I hereby license Blockchain Commons, LLC to: 25 | 26 | 1. do anything with my contributions that would otherwise infringe my copyright in them 27 | 28 | 2. do anything with my contributions that would otherwise infringe patents that I can or become able to license 29 | 30 | 3. sublicense these rights to others on any terms they like 31 | 32 | ## Reliability 33 | 34 | I understand that Blockchain Commons will rely on this license. I may not revoke this license. 35 | 36 | ## Awareness 37 | 38 | I promise that I am familiar with legal rules, like ["work made for hire" rules](http://worksmadeforhire.com), that can give employers and clients ownership of intellectual property in work that I do. I am also aware that legal agreements I might sign, like confidential information and invention assignment agreements, will usually give ownership of intellectual property in my work to employers, clients, and companies that I found. If someone else owns intellectual property in my work, I need their permission to license it. 39 | 40 | ## Copyright Guarantee 41 | 42 | I promise not to offer contributions to the project that contain copyrighted work that I do not have legally binding permission to contribute under these terms. When I offer a contribution with permission, I promise to document in the contribution who owns copyright in what work, and how they gave permission to contribute it. If I later become aware that one of my contributions may have copyrighted work of others that I did not have permission to contribute, I will notify Blockchain Commons, in confidence, immediately. 43 | 44 | ## Patent Guarantee 45 | 46 | I promise not to offer contributions to the project that I know infringe patents of others that I do not have permission to contribute under these terms. 47 | 48 | ## Open Source Guarantee 49 | 50 | I promise not to offer contributions that contain or depend on the work of others, unless that work is available under a license that [Blue Oak Council rates bronze or better](https://blueoakconcil.org/list), such as the MIT License, two- or three-clause BSD License, the Apache License Version 2.0, or the Blue Oak Model License 1.0.0. When I offer a contribution containing or depending on others' work, I promise to document in the contribution who licenses that work, along with copies of their license terms. 51 | 52 | ## Disclaimers 53 | 54 | ***As far as the law allows, my contributions come as is, without any warranty or condition. Other than under [Copyright Guarantee](#copyright-guarantee), [Patent Guarantee](#patent-guarantee), or [Open Source Guarantee](#open-source-guarantee), I will not be liable to anyone for any damages related to my contributions or this contributor license agreement, under any kind of legal claim.*** 55 | -----BEGIN PGP SIGNATURE----- 56 | 57 | iQIzBAEBCAAdFiEElDZS7jhEF2DD3DU2S2wvz4lHgK4FAmJGD8UACgkQS2wvz4lH 58 | gK4iKRAAsKfTUg/c1015APiSHO9yte8Q8eA2tuxV5kxK+OzA0PTRIlvw8RHLFyx+ 59 | /ToqCZHKlny/m7BZYqJyFSXCOeF99FDJqUZL9AxODBUx/S1dqQ9ppEGqH5LDMm0c 60 | vwsqWtkSEj/T3XNyIId7etidbdrnyKPFNXl4lDHRsdrMvhSQHImb1d/FPACAdJTl 61 | i3dDc9Y4Z75JYOjWKPoBYjAIh2gY3+8lk2bghQtQfs1Crf7kHxWjtjMHMoUv+Qo3 62 | d6f4F6R2rpI5cr9pDHYa+IWe9Dfi3FgWA/Vvk/QC/FAvIm2BKY6f8xcX6XsSRPuK 63 | UJEmNJt1VTZz6HKw9s/vvaXybkZ6F+vLHE+Fjbn3zzjd1foiY6RXVF+XNcCOCppz 64 | lT1bWI9BU9rfNMj1x2WPQ1pJHO9m12Z/j7qjJTYZgQod6artiq2NXrHHZaMjSi0A 65 | wNz7tcH5MKahWAlIXBkPGevExXA5ncYU0CHKAABj0TVAy9bn9Gic68z0vPYwl+N9 66 | lfi0htPmAx5gL5u8+4eY/8y7BSzHp7NZHbYSAI36rbHc4JoaFAwyWIMo87bzD04B 67 | FXEJBNS8NYAjXPYKzp43mds0b7174XXFY6o2+uJDNDseNt93fDzgBa4UyUBUhdql 68 | iM8XELPLhgmEW1eRwwseRykDodQizJezPmPJxWNMjgOH1RZiT3k= 69 | =I4QP 70 | -----END PGP SIGNATURE----- 71 | -------------------------------------------------------------------------------- /CLA.md: -------------------------------------------------------------------------------- 1 | # Contributor License Agreement 2 | 3 | Version 1.0 4 | 5 | Name: `$name` 6 | 7 | E-Mail: `$email` 8 | 9 | Legal Jurisdiction: Wyoming, United States of America 10 | 11 | Project: https://github.com/BlockchainCommons/seedtool-cli 12 | 13 | Date: `$date` 14 | 15 | ## Purpose 16 | 17 | This agreement gives Blockchain Commons, LLC the permission it needs in order to accept my contributions into its open software project and to manage the intellectual property in that project over time. 18 | 19 | ## License 20 | 21 | I hereby license Blockchain Commons, LLC to: 22 | 23 | 1. do anything with my contributions that would otherwise infringe my copyright in them 24 | 25 | 2. do anything with my contributions that would otherwise infringe patents that I can or become able to license 26 | 27 | 3. sublicense these rights to others on any terms they like 28 | 29 | ## Reliability 30 | 31 | I understand that Blockchain Commons will rely on this license. I may not revoke this license. 32 | 33 | ## Awareness 34 | 35 | I promise that I am familiar with legal rules, like ["work made for hire" rules](http://worksmadeforhire.com), that can give employers and clients ownership of intellectual property in work that I do. I am also aware that legal agreements I might sign, like confidential information and invention assignment agreements, will usually give ownership of intellectual property in my work to employers, clients, and companies that I found. If someone else owns intellectual property in my work, I need their permission to license it. 36 | 37 | ## Copyright Guarantee 38 | 39 | I promise not to offer contributions to the project that contain copyrighted work that I do not have legally binding permission to contribute under these terms. When I offer a contribution with permission, I promise to document in the contribution who owns copyright in what work, and how they gave permission to contribute it. If I later become aware that one of my contributions may have copyrighted work of others that I did not have permission to contribute, I will notify Blockchain Commons, in confidence, immediately. 40 | 41 | ## Patent Guarantee 42 | 43 | I promise not to offer contributions to the project that I know infringe patents of others that I do not have permission to contribute under these terms. 44 | 45 | ## Open Source Guarantee 46 | 47 | I promise not to offer contributions that contain or depend on the work of others, unless that work is available under a license that [Blue Oak Council rates bronze or better](https://blueoakconcil.org/list), such as the MIT License, two- or three-clause BSD License, the Apache License Version 2.0, or the Blue Oak Model License 1.0.0. When I offer a contribution containing or depending on others' work, I promise to document in the contribution who licenses that work, along with copies of their license terms. 48 | 49 | ## Disclaimers 50 | 51 | ***As far as the law allows, my contributions come as is, without any warranty or condition. Other than under [Copyright Guarantee](#copyright-guarantee), [Patent Guarantee](#patent-guarantee), or [Open Source Guarantee](#open-source-guarantee), I will not be liable to anyone for any damages related to my contributions or this contributor license agreement, under any kind of legal claim.*** 52 | 53 | --- 54 | 55 | To sign this Contributor License Agreement, fill in `$name`, `$email`, and `$date` above. Then sign using GPG using the following command `gpg --armor --clearsign --output CLA.YOURGITHUBNAME.YOURGPGFINGERPRINT.asc CLA.md`, then either submit your signed Contributor License Agreement to this repo as a GPG signed Pull Request or email it to [ChristopherA@BlockchainCommons.com](mailto:ChristopherA@BlockchainCommons.com). 56 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in this repo. 2 | 3 | * @ChristopherA @wolfmcnally 4 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's: 4 | 5 | - Reporting a bug 6 | - Discussing the current state of the code 7 | - Submitting a fix 8 | - Proposing new features 9 | - Becoming a maintainer 10 | 11 | ## We Develop with Github 12 | We use GitHub to host code, to track issues and feature requests, as well as accept Pull Requests. 13 | 14 | ## Report bugs using Github's [issues](https://github.com/BlockchainCommons/seedtool-cli/issues) 15 | We use GitHub issues to track public bugs. 16 | 17 | If you find bugs, mistakes, inconsistencies in this project's code or documents, please let us know by [opening a new issue](https://github.com/BlockchainCommons/seedtool-cli/issues), but consider searching through existing issues first to check and see if the problem has already been reported. If it has, it never hurts to add a quick "+1" or "I have this problem too". This helps prioritize the most common problems and requests. 18 | 19 | ## Write bug reports with detail, background, and sample code 20 | [This is an example](http://stackoverflow.com/q/12488905/180626) of a good bug report by @briandk. Here's [another example from craig.hockenberry](http://www.openradar.me/11905408). 21 | 22 | **Great Bug Reports** tend to have: 23 | 24 | - A quick summary and/or background 25 | - Steps to reproduce 26 | - Be specific! 27 | - Give sample code if you can. [The stackoverflow bug report](http://stackoverflow.com/q/12488905/180626) includes sample code that *anyone* with a base R setup can run to reproduce what I was seeing 28 | - What you expected would happen 29 | - What actually happens 30 | - Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) 31 | 32 | People *love* thorough bug reports. I'm not even kidding. 33 | 34 | ## Submitting code changes through Pull Requests 35 | 36 | Simple Pull Requests to fix typos, document, or fix small bugs are always welcome. 37 | 38 | We ask that more significant improvements to the project be first proposed before anybody starts to code as an [issue](https://github.com/BlockchainCommons/seedtool-cli/issues) or as a [draft Pull Request](https://github.com/BlockchainCommons/seedtool-cli/pulls) (GitHub has a nice new feature for simple Pull Requests called [Draft Pull Requests](https://github.blog/2019-02-14-introducing-draft-pull-requests/). This gives other contributors a chance to point you in the right direction, give feedback on the design, and maybe point out if related work is already under way. 39 | 40 | ## We Use [Github Flow](https://guides.github.com/introduction/flow/index.html), So All Code Changes Happen Through Pull Requests 41 | Pull Requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your Pull Requests: 42 | 43 | 1. Fork the repo and create your branch from `master`. 44 | 2. If you've added code that should be tested, add tests. 45 | 3. If you've changed APIs, update the documentation. 46 | 4. Ensure the test suite passes. 47 | 5. Make sure your code lints. 48 | 6. Issue that Pull Request! 49 | 50 | ## Any code contributions you make will be under the BSD-2-Clause Plus Patent License 51 | In short, when you submit code changes, your submissions are understood will be available under the same [BSD-2-Clause Plus Patent License](./LICENSE.md) that covers the project. We also ask all code contributors to GPG sign the [Contributor License Agreement (CLA.md)](./CLA.md) to protect future users of this project. Feel free to contact the maintainers if that's a concern. 52 | 53 | ## Use a Consistent Coding Style 54 | * We indent using two spaces (soft tabs) 55 | * We ALWAYS put spaces after list items and method parameters ([1, 2, 3], not [1,2,3]), around operators (x += 1, not x+=1), and around hash arrows. 56 | * This is open source software. Consider the people who will read your code, and make it look nice for them. It's sort of like driving a car: Perhaps you love doing donuts when you're alone, but with passengers the goal is to make the ride as smooth as possible. 57 | 58 | ## References 59 | 60 | Portions of this CONTRIBUTING.md document were adopted from best practices of a number of open source projects, including: 61 | * [Facebook's Draft](https://github.com/facebook/draft-js/blob/a9316a723f9e918afde44dea68b5f9f39b7d9b00/CONTRIBUTING.md) 62 | * [IPFS Contributing](https://github.com/ipfs/community/blob/master/CONTRIBUTING.md) 63 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:20.04 as build-stage 2 | ARG DEBIAN_FRONTEND=noninteractive 3 | RUN apt-get update -y 4 | # Install build dependencies 5 | RUN apt-get install -y git 6 | RUN apt-get install -y build-essential 7 | RUN apt-get install -y libc++-10-dev libc++abi-10-dev 8 | RUN apt-get install -y lsb-release wget software-properties-common 9 | RUN wget https://apt.llvm.org/llvm.sh 10 | RUN chmod +x llvm.sh 11 | RUN ./llvm.sh 10 # version 10 12 | # Build seedtool-cli 13 | ENV CC="clang-10" 14 | ENV CXX="clang++-10" 15 | COPY . /seedtool-cli 16 | WORKDIR /seedtool-cli 17 | RUN git submodule update --init --recursive 18 | RUN CC="clang-10" CXX="clang++-10" ./build.sh 19 | 20 | # Export built executable to a minimal runtime image and run as an unprivileged 21 | # user. 22 | FROM ubuntu:20.04 23 | ARG DEBIAN_FRONTEND=noninteractive 24 | # Install runtime dependencies 25 | RUN apt-get update -y 26 | RUN apt-get install -y libc++1 libc++abi1 27 | # Install binary 28 | COPY --from=build-stage /seedtool-cli/src/seedtool /usr/local/bin/seedtool 29 | # Create an unprivileged user 30 | RUN useradd --create-home --user-group user 31 | USER user 32 | ENTRYPOINT ["seedtool"] 33 | -------------------------------------------------------------------------------- /Docs/Install-Windows.md: -------------------------------------------------------------------------------- 1 | # Building Seedtool on Windows 2 | 3 | This document describes building `seedtool` with `MSYS2` and its usage on `Windows 10` 64-bit. 4 | 5 | ## Installing MSYS2 and Packages 6 | 7 | 1. Install `MSYS2` by downloading the installer and following the installation guide in [www.msys2.org](www.msys2.org). 8 | 2. Run `MSYS2` and make sure the package database is updated: 9 | ```bash 10 | # pacman -Syu 11 | # pacman -Su 12 | ``` 13 | 3. Next, install the compiler and the required packages: 14 | ```bash 15 | # pacman -S mingw-w64-x86_64-clang 16 | # pacman -S patch 17 | # pacman -S git 18 | # pacman -S make 19 | # pacman -S mingw-w64-x86_64-libc++ 20 | # pacman -S autoconf 21 | # pacman -S automake1.8 22 | ``` 23 | 24 | ## Compiling Seedtool 25 | 26 | 1. Clone `seedtool-cli`, e.g. into `C:\msys64\home` 27 | 2. Open `MSYS2 MinGW 64-bit` application and `cd` into `C:\msys64\home\seedtool-cli` 28 | 3. Run the build script with: 29 | ```bash 30 | # export CC="clang" && export CXX="clang++" && ./build.sh 31 | ``` 32 | 4. Install: 33 | ```bash 34 | # make install 35 | ``` 36 | You can now freely use `seedtool` inside `MSYS2 MinGW 64-bit` console. 37 | 38 | ### Running Seedtool as a Native Windows App 39 | 40 | To be able to use `seedtool` as a native app on Windows outside `msys2/mingw64`, you have to expose three files to the system: `seedtool.exe`, `libc++.dll`, and `libunwind.dll`, which all reside in `C:\msys64\mingw64\bin`. 41 | 42 | To do so, add that folder to the `Windows PATH` by the following command in `Windows Cmd`: 43 | ```bash 44 | # set PATH=%PATH%;C:\msys64\mingw64\bin 45 | ``` 46 | That's it. Now you can use `seedtool` as a native Windows app in the Windows command-line tool. 47 | 48 | *Note:* If you want to pipe seedtool ouput into a QR code generator, you could use: 49 | 50 | ```bash 51 | # seedtool --ur | python -c "import sys; print(sys.stdin.readlines()[0].upper())" | qr > seedqrcode.png 52 | ``` 53 | 54 | For this you'll need `Python` and the following package: 55 | 56 | ```bash 57 | # pip install qrcode[pil] 58 | ``` 59 | 60 | -------------------------------------------------------------------------------- /Docs/Usage.md: -------------------------------------------------------------------------------- 1 | # 🌱 Seedtool Usage Examples 2 | 3 | ## Basic Information 4 | 5 | ### Display usage and help information 6 | 7 | ``` 8 | $ seedtool --help 9 | ``` 10 | 11 | ## Seed Generation 12 | 13 | ### Generate a cryptographically-strong 16-byte seed 14 | 15 | ``` 16 | $ seedtool 17 | 8935a8068526d84da555cdb741a3b8a8 18 | ``` 19 | 20 | ### Generate a seed using entropy provided as coin flips 21 | 22 | ``` 23 | $ seedtool --in bits 1110110001110111 24 | 8d933e43b1bc8f2e3fc27adc98ad4534 25 | ``` 26 | 27 | ### Generate a 32-byte seed using entropy provided as cards drawn from a deck of playing cards 28 | 29 | ``` 30 | $ seedtool --count 32 --in cards 6c9s8c7c9c4cah6c2sjs7d5c2s4c4dqs 31 | 7df301924511326d7350be14c9e7176d98e945f9ad0ed034726ad4ee0de59c25 32 | ``` 33 | 34 | ## BIP-39 Mnemonics 35 | 36 | ### Encode a 16-byte seed as BIP-39 37 | 38 | ``` 39 | $ seedtool --in hex --out bip39 8935a8068526d84da555cdb741a3b8a8 40 | matrix pull accuse apart horn chat next rifle resemble artist until eye 41 | ``` 42 | 43 | ### Decode BIP-39 mnemonics to hex 44 | 45 | ``` 46 | $ seedtool --in bip39 "matrix pull accuse apart horn chat next rifle resemble artist until eye" 47 | 8935a8068526d84da555cdb741a3b8a8 48 | ``` 49 | 50 | ## Bytewords 51 | 52 | ### Decode Bytewords to hex 53 | 54 | ``` 55 | $ seedtool --in btw "deli need cats taxi dice door webs vows free zero legs wall half waxy trip oval memo sets rock hill" 56 | 279b18d0282aefe845fb83e956eed8a6 57 | ``` 58 | 59 | ## SSKR 60 | 61 | ### Generate a 16-byte seed and encode it using SSKR as 3 shares, 2 of which are required for recovery 62 | 63 | ``` 64 | $ seedtool --out sskr --group 2-of-3 65 | tuna acid epic gyro many meow able acid able mild fern pool door purr calm trip cyan flew zest cats tuna omit figs bias acid aunt keys play frog 66 | tuna acid epic gyro many meow able acid acid keep undo peck poem kiwi jazz cola luck hope rock into film jolt lava flux rust gala sets ruin toil 67 | tuna acid epic gyro many meow able acid also girl void oval fish exam veto gala inky keys jump visa barn cusp high miss monk jazz numb dice foxy 68 | ``` 69 | 70 | ### Recover a SSKR-encoded seed using 2 of the 3 shares 71 | 72 | ``` 73 | $ seedtool --in sskr 74 | tuna acid epic gyro many meow able acid able mild fern pool door purr calm trip cyan flew zest cats tuna omit figs bias acid aunt keys play frog 75 | tuna acid epic gyro many meow able acid also girl void oval fish exam veto gala inky keys jump visa barn cusp high miss monk jazz numb dice foxy 76 | ^D 77 | 9d347f841a4e2ce6bc886e1aee74d824 78 | ``` 79 | 80 | ## UR 81 | 82 | ### Generate a seed, encode it as UR, transform it to upper case, display it on the console, and encode it to a QR Code in the file "seedqrcode.png" 83 | 84 | ``` 85 | $ seedtool --ur | tr [:lower:] [:upper:] | tee /dev/tty | qrencode -o seedqrcode.png -l L 86 | UR:SEED/OEADGDJOCNNEESSPDECECMVLFMLUOSBTDWQZFEAOTPIECFFDJZPYTAIEKK 87 | ``` 88 | 89 | ![](../manual-images/seedqrcode.png) 90 | 91 | ### Generate a 64-byte seed using a deterministic random number generator and encode it as a multi-part UR with a maximum fragment size of 20 bytes 92 | 93 | ``` 94 | $ seedtool --deterministic=TEST --count 64 --ur=20 95 | ur:seed/1-4/lpadaacsfycyutrpgrfggyoyadhdfznteelblrcygldwvarflojtcywyhtmtdpeh 96 | ur:seed/2-4/lpaoaacsfycyutrpgrfggyjytpdkfwprylienshnjnpluypmamtkmybswddnkolg 97 | ur:seed/3-4/lpaxaacsfycyutrpgrfggyjkspvseesawmrltdlnlgkplfbkqzzoglfejtgylpfw 98 | ur:seed/4-4/lpaaaacsfycyutrpgrfggyoyaegsnedtrowsdpgtimmwzspfqdjkhshyqzwfssln 99 | ``` 100 | 101 | ### Same as above, but generate 5 additional parts using fountain codes 102 | 103 | ``` 104 | $ seedtool --deterministic=TEST --count 64 --ur=20 --parts 5 105 | ur:seed/1-4/lpadaacsfycyutrpgrfggyoyadhdfznteelblrcygldwvarflojtcywyhtmtdpeh 106 | ur:seed/2-4/lpaoaacsfycyutrpgrfggyjytpdkfwprylienshnjnpluypmamtkmybswddnkolg 107 | ur:seed/3-4/lpaxaacsfycyutrpgrfggyjkspvseesawmrltdlnlgkplfbkqzzoglfejtgylpfw 108 | ur:seed/4-4/lpaaaacsfycyutrpgrfggyoyaegsnedtrowsdpgtimmwzspfqdjkhshyqzwfssln 109 | ur:seed/5-4/lpahaacsfycyutrpgrfggyoyaegsnedtrowsdpgtimmwzspfqdjkhshytnlburst 110 | ur:seed/6-4/lpamaacsfycyutrpgrfggyoyadhdfznteelblrcygldwvarflojtcywylofxjerl 111 | ur:seed/7-4/lpataacsfycyutrpgrfggytdsopfjyheursphfnssrhkierpfnmdghpywnylisbt 112 | ur:seed/8-4/lpayaacsfycyutrpgrfggyjytpdkfwprylienshnjnpluypmamtkmybsykpamtlp 113 | ur:seed/9-4/lpasaacsfycyutrpgrfggyjytpdkfwprylienshnjnpluypmamtkmybsndfslgss 114 | ``` 115 | 116 | ### Recover the seed from UR using a subset of the generated parts 117 | 118 | ``` 119 | $ seedtool --in ur 120 | ur:seed/1-4/lpadaacsfycyutrpgrfggyoyadhdfznteelblrcygldwvarflojtcywyhtmtdpeh 121 | ur:seed/3-4/lpaxaacsfycyutrpgrfggyjkspvseesawmrltdlnlgkplfbkqzzoglfejtgylpfw 122 | ur:seed/5-4/lpahaacsfycyutrpgrfggyoyaegsnedtrowsdpgtimmwzspfqdjkhshytnlburst 123 | ur:seed/7-4/lpataacsfycyutrpgrfggytdsopfjyheursphfnssrhkierpfnmdghpywnylisbt 124 | ur:seed/9-4/lpasaacsfycyutrpgrfggyjytpdkfwprylienshnjnpluypmamtkmybsndfslgss 125 | ^D 126 | 9d347f841a4e2ce6bc886e1aee74d82442b2f7649c606daedbad06cf8f0f73c8e834c2ebb7d2868d75820ab4fb4e45a1004c9f29b8ef2d4d6a94fab0b373615e 127 | ``` 128 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Unless otherwise noted (either in /README.md or in the file's header comments) the contents of this repository are released under the following license: 2 | 3 | BSD-2-Clause Plus Patent License 4 | 5 | SPDX-License-Identifier: [BSD-2-Clause-Patent](https://spdx.org/licenses/BSD-2-Clause-Patent.html) 6 | 7 | Copyright © 2019 Blockchain Commons, LLC 8 | 9 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 13 | Subject to the terms and conditions of this license, each copyright holder and contributor hereby grants to those receiving rights under this license a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except for failure to satisfy the conditions of this license) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer this software, where such license applies only to those patent claims, already acquired or hereafter acquired, licensable by such copyright holder or contributor that are necessarily infringed by: 14 | 15 | (a) their Contribution(s) (the licensed copyrights of copyright holders and non-copyrightable additions of contributors, in source or binary form) alone; or 16 | (b) combination of their Contribution(s) with the work of authorship to which such Contribution(s) was added by such copyright holder or contributor, if, at the time the Contribution is added, such addition causes such combination to be necessarily infringed. The patent license shall not apply to any other combinations which include the Contribution. 17 | Except as expressly stated above, no rights or licenses from any copyright holder or contributor is granted under this license, whether expressly, by implication, estoppel or otherwise. 18 | 19 | DISCLAIMER 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # @configure_input@ 2 | 3 | # 4 | # Makefile.in 5 | # 6 | # Copyright © 2020 by Blockchain Commons, LLC 7 | # Licensed under the "BSD-2-Clause Plus Patent License" 8 | # 9 | 10 | UNAME := $(shell uname) 11 | ifeq ($(UNAME), Linux) 12 | SHELL := /bin/bash 13 | else ifeq ($(findstring MINGW64, $(UNAME)), MINGW64) 14 | # on windows building with msys2/mingw64 15 | SHELL := /bin/bash 16 | endif 17 | 18 | # Package-specific substitution variables 19 | package = @PACKAGE_NAME@ 20 | version = @PACKAGE_VERSION@ 21 | 22 | # Prefix-specific substitution variables 23 | prefix = @prefix@ 24 | exec_prefix = @exec_prefix@ 25 | bindir = @bindir@ 26 | 27 | # VPATH-specific substitution variables 28 | srcdir = @srcdir@ 29 | VPATH = @srcdir@ 30 | 31 | # Terminal colors 32 | RED=`tput setaf 1` 33 | GREEN=`tput setaf 2` 34 | RESET=`tput sgr0` 35 | 36 | .PHONY: all clean seedtool check lint 37 | all clean seedtool check lint: 38 | source set_build_paths.sh && cd src && $(MAKE) $@ 39 | 40 | .PHONY: install uninstall 41 | install uninstall: 42 | source set_build_paths.sh && cd src && $(MAKE) $@ 43 | 44 | config.status: configure 45 | ./config.status --recheck 46 | 47 | .PHONY: distclean 48 | distclean: 49 | cd src && $(MAKE) $@ 50 | rm -f Makefile 51 | rm -rf autom4te.cache 52 | rm -f autoscan.log 53 | rm -f configure.scan configure.status config.log config.status config.h 54 | for d in deps/*; do \ 55 | if [[ -d "$d" ]]; then \ 56 | pushd $d; \ 57 | make clean; \ 58 | popd; \ 59 | fi; \ 60 | done 61 | rm -rf sysroot 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 🌱 Blockchain Commons seedtool-cli 2 | 3 | ![macos](https://github.com/BlockchainCommons/seedtool-cli/workflows/macOS/badge.svg) 4 | ![linux](https://github.com/BlockchainCommons/seedtool-cli/workflows/linux/badge.svg) 5 | ![linter](https://github.com/BlockchainCommons/seedtool-cli/workflows/linter/badge.svg) 6 | 7 | ### _by [Wolf McNally](https://www.github.com/wolfmcnally) and [Christopher Allen](https://www.github.com/ChristopherA)_ 8 | 9 | *    ***part of the [crypto commons](https://github.com/BlockchainCommons/crypto-commons/blob/master/README.md) technology family*** 10 | * ***part of the [gordian](https://github.com/BlockchainCommons/gordian/blob/master/README.md) technology family*** 11 | 12 |

13 | 14 |

15 | 16 | ## Deprecation of C++ SeedTool 17 | 18 | This repo contains the original SeedTool written in C++, and is now deprecated. The [new SeedTool is written in Rust](https://github.com/BlockchainCommons/seedtool-cli-rust) and is a complete rewrite. The new SeedTool's inputs and outputs are compatible with the old SeedTool, and most of the same command line options are supported. The new SeedTool is more flexible and extensible, and is designed to support additional functionality. 19 | 20 | ## Introduction 21 | 22 | `seedtool` is a command-line tool for creating and transforming cryptographic seeds of the sort commonly used by blockchain applications. 23 | 24 | It exercises the various cryptographic C libraries created by Blockchain Commons, as described in the Dependencies section. 25 | 26 | ## Status - Feature-Complete Beta 27 | 28 | Seedtool is now considered feature-complete and is entering beta-level testing. 29 | 30 | ## Dependencies 31 | 32 | Seedtool exercises the following Blockchain Commons libraries: 33 | 34 | * [`bc-crypto-base`](https://github.com/blockchaincommons/bc-crypto-base) 35 | * [`bc-shamir`](https://github.com/blockchaincommons/bc-shamir) 36 | * [`bc-sskr`](https://github.com/blockchaincommons/bc-sskr) 37 | * [`bc-bip39`](https://github.com/blockchaincommons/bc-bip39) 38 | * [`bc-ur`](https://github.com/blockchaincommons/bc-ur) 39 | 40 | It also requires the following additional programs: 41 | 42 | * [`GNU argp`](https://www.gnu.org/software/libc/manual/html_node/Argp.html) 43 | * [`CBOR Lite`](https://bitbucket.org/isode/cbor-lite) 44 | 45 | ### Tool Dependencies 46 | 47 | To build `seedtool` you'll need to use the following tools: 48 | 49 | - autotools - Gnu Build System from Free Software Foundation ([intro](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html)). 50 | 51 | ## Recommended Installation instructions 52 | 53 | The dependencies will be automatically installed as submodules when you run the build script. This is the recommended way to install. 54 | 55 | ### Build with Docker 56 | 57 | [Install docker](https://docs.docker.com/get-docker/) and run: 58 | 59 | ```bash 60 | # Build the image 61 | $ docker build -t seedtool-cli . 62 | # Run the container 63 | $ docker run --rm -it seedtool-cli --help 64 | ``` 65 | 66 | ### Build on MacOS 67 | 68 | ```bash 69 | $ brew install autoconf automake libtool 70 | ``` 71 | 72 | You must then download or clone this repo. Afterward, cd into the repo directory and: 73 | 74 | ```bash 75 | $ ./build.sh 76 | $ sudo make install 77 | ``` 78 | 79 | ### Build on Linux 80 | 81 | Make sure you have `llvm`/`clang`, `libc++` and `libc++abi` installed, all with 82 | a minimum recommended version 10. 83 | 84 | #### Build on Ubuntu and Debian 85 | 86 | ```bash 87 | $ sudo apt install build-essential 88 | 89 | $ wget https://apt.llvm.org/llvm.sh 90 | $ chmod +x llvm.sh 91 | $ sudo apt install lsb-release wget software-properties-common 92 | $ sudo ./llvm.sh 10 # version 10 93 | 94 | $ sudo apt-get install libc++-10-dev libc++abi-10-dev 95 | ``` 96 | 97 | ```bash 98 | $ sudo apt-get install git 99 | $ git clone https://github.com/BlockchainCommons/seedtool-cli.git 100 | $ cd seedtool-cli/ 101 | $ export CC="clang-10" && export CXX="clang++-10" && ./build.sh 102 | $ sudo make install 103 | ``` 104 | 105 | ### Build on Windows 106 | 107 | See [instructions here](Docs/Install-Windows.md). 108 | 109 | ## Alternative Installation Instructions 110 | 111 | The following sequence does *not* install the dependencies from submodules; instead they must be installed in the usual places on the build system, otherwise the `./configure` step below will fail. 112 | 113 | ```bash 114 | $ ./configure 115 | $ make 116 | $ sudo make install 117 | ``` 118 | *Note:* On Linux the first step is `./configure CC=clang-10 CXX=clang++-10` 119 | 120 | ## Incremental Build Instructions 121 | 122 | If you wish to make changes to the source code and rebuild: 123 | 124 | ```bash 125 | # Make source changes 126 | $ source set_build_paths.sh # sets shell variables used by make 127 | $ make clean # If you want a clean build 128 | $ make 129 | ``` 130 | 131 | ## Usage Instructions 132 | 133 | See [usage examples](Docs/Usage.md) for examples of using seedtool. 134 | 135 | ## Full Documentation 136 | 137 | See [`MANUAL.md`](Docs/MANUAL.md) for details, many more examples, and version history. 138 | 139 | ## Notes for Maintainers 140 | 141 | Before accepting a PR that can affect build or unit tests, make sure the following sequence of commands succeeds: 142 | 143 | ```bash 144 | $ ./build.sh 145 | $ make lint 146 | $ make check 147 | $ make distclean 148 | ``` 149 | 150 | `make lint` uses [Cppcheck](https://en.wikipedia.org/wiki/Cppcheck) to perform static analysis on the code. All PRs should pass with no warnings. 151 | 152 | ## Related Projects 153 | 154 | * [LetheKit](https://github.com/BlockchainCommons/bc-lethekit) is a parallel project that uses many of the same libraries, but in hardware. 155 | * [URKit](https://github.com/BlockchainCommons/URKit) is another example of our [bc-ur](https://github.com/BlockchainCommons/bc-ur) universal-reference library. 156 | 157 | ## Origin, Authors, Copyright & Licenses 158 | 159 | Unless otherwise noted (either in this [/README.md](./README.md) or in the file's header comments) the contents of this repository are Copyright © 2020 by Blockchain Commons, LLC, and are [licensed](./LICENSE) under the [spdx:BSD-2-Clause Plus Patent License](https://spdx.org/licenses/BSD-2-Clause-Patent.html). 160 | 161 | In most cases, the authors, copyright, and license for each file reside in header comments in the source code. When it does not we have attempted to attribute it accurately in the table below. 162 | 163 | This table below also establishes provenance (repository of origin, permalink, and commit id) for files included from repositories that are outside of this repository. Contributors to these files are listed in the commit history for each repository, first with changes found in the commit history of this repo, then in changes in the commit history of their repo of their origin. 164 | 165 | | File | From | Commit | Authors & Copyright (c) | License | 166 | | --------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------ | ----------------------------------------------------------- | 167 | | hkdf.c | [rustyrussell/ccan](https://github.com/rustyrussell/ccan/blob/master/ccan/crypto/hkdf_sha256/hkdf_sha256.c) | [d07f742](https://github.com/rustyrussell/ccan/commit/d07f742c5925b97ed558eb07aae285616f5df823) | 2016 [Rusty Russell](https://github.com/rustyrussell)
2020 Wolf McNally | [MIT](https://github.com/rustyrussell/ccan/blob/master/ccan/crypto/hkdf_sha256/LICENSE) 168 | | hkdf.h | [rustyrussell/ccan](https://github.com/rustyrussell/ccan/blob/master/ccan/crypto/hkdf_sha256/hkdf_sha256.h) | [d07f742](https://github.com/rustyrussell/ccan/commit/d07f742c5925b97ed558eb07aae285616f5df823) | 2016 [Rusty Russell](https://github.com/rustyrussell) | [MIT](https://github.com/rustyrussell/ccan/blob/master/ccan/crypto/hkdf_sha256/LICENSE) 169 | | randombytes.c | [dsprenkels/randombytes](https://github.com/dsprenkels/randombytes/blob/master/randombytes.c) | [6db39aa](https://github.com/dsprenkels/randombytes/commit/6db39aaae6bb9ab97beca00d81bcfe935c56c88d) | 2017-2019 [Daan Sprenkels](https://github.com/dsprenkels/) | [MIT](https://github.com/dsprenkels/randombytes/commit/73ae9b4fce2e62babdd6a480b53ad449dd745ed9) | 170 | | randombytes.h | [dsprenkels/randombytes](https://github.com/dsprenkels/randombytes/blob/master/randombytes.h) | [19fd002](https://github.com/dsprenkels/randombytes/commit/19fd002d9b7b001b333a671186a91231b60d821b) | 2017-2019 [Daan Sprenkels](https://github.com/dsprenkels/) | [MIT](https://github.com/dsprenkels/randombytes/commit/73ae9b4fce2e62babdd6a480b53ad449dd745ed9) | 171 | 172 | ### Tool Dependencies 173 | 174 | To build `seedtool` you'll need to use the following tools: 175 | 176 | - autotools - Gnu Build System from Free Software Foundation ([intro](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html)). 177 | 178 | ## Financial Support 179 | 180 | Seedtool is a project of [Blockchain Commons](https://www.blockchaincommons.com/). We are proudly a "not-for-profit" social benefit corporation committed to open source & open development. Our work is funded entirely by donations and collaborative partnerships with people like you. Every contribution will be spent on building open tools, technologies, and techniques that sustain and advance blockchain and internet security infrastructure and promote an open web. 181 | 182 | To financially support further development of Seedtool and other projects, please consider becoming a Patron of Blockchain Commons through ongoing monthly patronage as a [GitHub Sponsor](https://github.com/sponsors/BlockchainCommons). You can also support Blockchain Commons with bitcoins at our [BTCPay Server](https://btcpay.blockchaincommons.com/). 183 | 184 | ## Contributing 185 | 186 | We encourage public contributions through issues and pull-requests! Please review [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our development process. All contributions to this repository require a GPG signed [Contributor License Agreement](./CLA.md). 187 | 188 | ### Discussions 189 | 190 | The best place to talk about Blockchain Commons and its projects is in our GitHub Discussions areas. 191 | 192 | [**Gordian User Community**](https://github.com/BlockchainCommons/Gordian/discussions). For users of the Gordian reference apps, including [Gordian Coordinator](https://github.com/BlockchainCommons/iOS-GordianCoordinator), [Gordian Seed Tool](https://github.com/BlockchainCommons/GordianSeedTool-iOS), [Gordian Server](https://github.com/BlockchainCommons/GordianServer-macOS), [Gordian Wallet](https://github.com/BlockchainCommons/GordianWallet-iOS), and [SpotBit](https://github.com/BlockchainCommons/spotbit) as well as our whole series of [CLI apps](https://github.com/BlockchainCommons/Gordian/blob/master/Docs/Overview-Apps.md#cli-apps). This is a place to talk about bug reports and feature requests as well as to explore how our reference apps embody the [Gordian Principles](https://github.com/BlockchainCommons/Gordian#gordian-principles). 193 | 194 | [**Blockchain Commons Discussions**](https://github.com/BlockchainCommons/Community/discussions). For developers, interns, and patrons of Blockchain Commons, please use the discussions area of the [Community repo](https://github.com/BlockchainCommons/Community) to talk about general Blockchain Commons issues, the intern program, or topics other than those covered by the [Gordian Developer Community](https://github.com/BlockchainCommons/Gordian-Developer-Community/discussions) or the 195 | [Gordian User Community](https://github.com/BlockchainCommons/Gordian/discussions). 196 | 197 | ### Other Questions & Problems 198 | 199 | As an open-source, open-development community, Blockchain Commons does not have the resources to provide direct support of our projects. Please consider the discussions area as a locale where you might get answers to questions. Alternatively, please use this repository's [issues](./issues) feature. Unfortunately, we can not make any promises on response time. 200 | 201 | If your company requires support to use our projects, please feel free to contact us directly about options. We may be able to offer you a contract for support from one of our contributors, or we might be able to point you to another entity who can offer the contractual support that you need. 202 | 203 | ### Credits 204 | 205 | The following people directly contributed to this repository. You can add your name here by getting involved — the first step is to learn how to contribute from our [CONTRIBUTING.md](./CONTRIBUTING.md) documentation. 206 | 207 | | Name | Role | Github | Email | GPG Fingerprint | 208 | | ----------------- | ------------------- | ------------------------------------------------- | ------------------------------------- | -------------------------------------------------- | 209 | | Christopher Allen | Principal Architect | [@ChristopherA](https://github.com/ChristopherA) | \ | FDFE 14A5 4ECB 30FC 5D22 74EF F8D3 6C91 3574 05ED | 210 | | Wolf McNally | Project Lead | [@WolfMcNally](https://github.com/wolfmcnally) | \ | 9436 52EE 3844 1760 C3DC  3536 4B6C 2FCF 8947 80AE | 211 | 212 | ## Responsible Disclosure 213 | 214 | We want to keep all our software safe for everyone. If you have discovered a security vulnerability, we appreciate your help in disclosing it to us in a responsible manner. We are unfortunately not able to offer bug bounties at this time. 215 | 216 | We do ask that you offer us good faith and use best efforts not to leak information or harm any user, their data, or our developer community. Please give us a reasonable amount of time to fix the issue before you publish it. Do not defraud our users or us in the process of discovery. We promise not to bring legal action against researchers who point out a problem provided they do their best to follow the these guidelines. 217 | 218 | ## Reporting a Vulnerability 219 | 220 | Please report suspected security vulnerabilities in private via email to ChristopherA@BlockchainCommons.com (do not use this email for support). Please do NOT create publicly viewable issues for suspected security vulnerabilities. 221 | 222 | The following keys may be used to communicate sensitive information to developers: 223 | 224 | | Name | Fingerprint | 225 | | ----------------- | -------------------------------------------------- | 226 | | Christopher Allen | FDFE 14A5 4ECB 30FC 5D22 74EF F8D3 6C91 3574 05ED | 227 | 228 | You can import a key by running the following command with that individual’s fingerprint: `gpg --recv-keys ""` Ensure that you put quotes around fingerprints that contain spaces. 229 | -------------------------------------------------------------------------------- /bootstrap.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | autoreconf --install 4 | automake --add-missing --copy >/dev/null 2>&1 5 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git submodule init 4 | git submodule update 5 | 6 | source set_build_paths.sh 7 | 8 | # Terminal colors 9 | RED=`tput setaf 1` 10 | GREEN=`tput setaf 2` 11 | BLUE=`tput setaf 4` 12 | RESET=`tput sgr0` 13 | 14 | echo "${BLUE}== bc-crypto-base ==${RESET}" 15 | 16 | pushd deps/bc-crypto-base 17 | ./configure --prefix ${SYSROOT} 18 | make check 19 | make install 20 | popd 21 | 22 | echo "${BLUE}== bc-shamir ==${RESET}" 23 | 24 | pushd deps/bc-shamir 25 | ./configure --prefix ${SYSROOT} 26 | make check 27 | make install 28 | popd 29 | 30 | echo "${BLUE}== bc-sskr ==${RESET}" 31 | 32 | pushd deps/bc-sskr 33 | ./configure --prefix ${SYSROOT} 34 | make check 35 | make install 36 | popd 37 | 38 | echo "${BLUE}== bc-bip39 ==${RESET}" 39 | 40 | pushd deps/bc-bip39 41 | ./configure --prefix ${SYSROOT} 42 | make check 43 | make install 44 | popd 45 | 46 | echo "${BLUE}== bc-ur ==${RESET}" 47 | 48 | pushd deps/bc-ur 49 | ./configure --prefix ${SYSROOT} 50 | make check 51 | make install 52 | popd 53 | 54 | echo "${BLUE}== argp-standalone ==${RESET}" 55 | 56 | pushd deps/argp-standalone/argp-standalone 57 | set +e 58 | patch -N <../patch-argp-fmtstream.h 59 | set -e 60 | ./configure --prefix ${SYSROOT} 61 | make install 62 | cp libargp.a ${SYSROOT}/lib/ 63 | cp argp.h ${SYSROOT}/include/ 64 | popd 65 | 66 | echo "${BLUE}== seedtool ==${RESET}" 67 | 68 | ./configure 69 | make clean 70 | make check 71 | echo "${GREEN}*** Seedtool built.${RESET}" 72 | echo "${GREEN}Next step: sudo make install${RESET}" 73 | -------------------------------------------------------------------------------- /build/build-tailsOS.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:latest as base 2 | ARG DEBIAN_FRONTEND=noninteractive 3 | WORKDIR /app 4 | COPY . source 5 | COPY .git source/.git 6 | 7 | RUN apt update -y 8 | RUN apt install -y \ 9 | build-essential autogen libtool shtool \ 10 | clang llvm lld libstdc++6 libc++-dev libc++1 libc++abi1 \ 11 | git-buildpackage \ 12 | git \ 13 | coreutils binutils \ 14 | bash 15 | WORKDIR source 16 | FROM base 17 | ARG DEBIAN_FRONTEND=noninteractive 18 | SHELL ["/bin/bash", "-c"] 19 | RUN chmod -x debian/clean 20 | RUN ln -svf /usr/bin/lld /usr/bin/ld 21 | RUN git submodule update 22 | RUN cat debian/patches/series | xargs -I{} patch -f --strip=1 -i "debian/patches/{}" || true 23 | RUN patch -f --strip=1 -i debian/patches/bc-ur-build-tails.diff || true 24 | 25 | # FIXME(nochiel) It would be nice if running this line compiled the packaged the files we care about. 26 | RUN gbp buildpackage --git-upstream-tree=master --git-debian-branch=debian/latest --git-ignore-new --git-force-create --git-submodules -------------------------------------------------------------------------------- /build/packaging.md: -------------------------------------------------------------------------------- 1 | # Packaging for Debian 2 | - Run `git checkout debian/latest` 3 | 4 | Apply the patches listed in `debian/patches/series`. They should apply cleanly before the repository can be compiled. 5 | 6 | ```sh 7 | cat debian/patches/series | xargs -I{} patch -f --strip=1 -i "debian/patches/{}" 8 | ``` 9 | 10 | To build a Debian package run the following command in a checked-out `debian/latest` branch: `gbp buildpackage --git-upstream-tree=master --git-debian-branch=debian/latest --git-ignore-new --git-force-create --git-submodules` 11 | 12 | The relevant build artefacts can be found using `ls ../`. 13 | 14 | # Packaging for TailsOS 15 | - The `tails/latest` branch is always based on the `debian/latest` branch. 16 | - Run `git checkout tails/latest` 17 | - Run `docker build --tag=seedtool-tails --file build-tailsOS.Dockerfile .` 18 | - `/app/source` will contain a copy of the Seedtool source code. 19 | - `app` wiil contain all the `.deb` and source code archive files for distribution. 20 | - Run `docker container run --name seedtool-tails -it build-seedtool-tails bash` 21 | - Run `docker container cp seedtool-tails:/app seedtool-tails-build` 22 | - The directory `seedtool-tails-build/` will now container the output artefacts needed for Tails. 23 | 24 | 25 | ## Possible errors and how to deal with them 26 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.69]) 5 | AC_INIT([seedtool-cli], [0.11.0]) 6 | AC_CONFIG_SRCDIR([src/seedtool.cpp]) 7 | AC_CONFIG_HEADERS([src/config.h]) 8 | AC_CONFIG_AUX_DIR([build-aux]) 9 | 10 | # Checks for programs. 11 | AC_PROG_CXX 12 | AC_PROG_CC 13 | AC_PROG_INSTALL 14 | AC_PROG_MAKE_SET 15 | 16 | # on windows/msys2/mingw64: 17 | AS_CASE([$(uname -s)], 18 | [*MINGW*], [LIBS=-lws2_32], 19 | [LIBS=] 20 | ) 21 | 22 | # Checks for libraries. 23 | AC_CHECK_LIB([bc-crypto-base], [sha256_Raw], [], [ 24 | echo "### Error! libbc-crypto-base must be installed first." 25 | exit -1 26 | ]) 27 | AC_CHECK_LIB([bc-shamir], [split_secret], [], [ 28 | echo "### Error! libbc-shamir must be installed first." 29 | exit -1 30 | ]) 31 | AC_CHECK_LIB([bc-sskr], [sskr_generate], [], [ 32 | echo "### Error! libbc-sskr must be installed first." 33 | exit -1 34 | ]) 35 | AC_CHECK_LIB([bc-bip39], [bip39_mnemonic_from_word], [], [ 36 | echo "### Error! libbc-bip39 must be installed first." 37 | exit -1 38 | ]) 39 | AC_CHECK_LIB([bc-ur], [ur_crc32n], [], [ 40 | echo "### Error! libbc-ur must be installed first." 41 | exit -1 42 | ]) 43 | AC_CHECK_LIB([argp], [argp_parse], [], [ 44 | echo "### Error! argp must be installed first. Try 'brew install argp-standalone'." 45 | exit -1 46 | ]) 47 | 48 | # Checks for header files. 49 | AC_CHECK_HEADERS([fcntl.h memory.h stdint.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h unistd.h stddef.h]) 50 | 51 | # Checks for typedefs, structures, and compiler characteristics. 52 | AC_CHECK_HEADER_STDBOOL 53 | AC_C_INLINE 54 | AC_TYPE_SIZE_T 55 | AC_TYPE_SSIZE_T 56 | AC_TYPE_UINT16_T 57 | AC_TYPE_UINT32_T 58 | AC_TYPE_UINT64_T 59 | AC_TYPE_UINT8_T 60 | AC_TYPE_INT16_T 61 | AC_TYPE_INT32_T 62 | 63 | # Checks for library functions. 64 | AC_FUNC_MALLOC 65 | AC_CHECK_FUNCS([memset strerror]) 66 | 67 | AC_CONFIG_FILES([Makefile 68 | src/Makefile]) 69 | AC_OUTPUT 70 | -------------------------------------------------------------------------------- /debian/README.Debian: -------------------------------------------------------------------------------- 1 | seedtool-cli for Debian 2 | ---------------------- 3 | 4 | 5 | 6 | -- unknown Mon, 06 Feb 2023 14:50:21 +0300 7 | -------------------------------------------------------------------------------- /debian/README.source: -------------------------------------------------------------------------------- 1 | seedtool-cli for Debian 2 | ---------------------- 3 | 4 | 6 | 7 | 8 | 9 | -- unknown Mon, 06 Feb 2023 14:50:21 +0300 10 | 11 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | seedtool-cli (0.9.1-1) UNRELEASED; urgency=medium 2 | 3 | * Initial release for Debian packaging. 4 | 5 | -- Nick Ochiel Mon, 06 Feb 2023 14:50:21 +0300 6 | -------------------------------------------------------------------------------- /debian/clean: -------------------------------------------------------------------------------- 1 | deps/argp-standalone/argp-standalone/Makefile 2 | deps/argp-standalone/argp-standalone/aclocal.m4 3 | deps/argp-standalone/argp-standalone/compile 4 | deps/argp-standalone/argp-standalone/config.h 5 | deps/argp-standalone/argp-standalone/config.log 6 | deps/argp-standalone/argp-standalone/config.status 7 | deps/argp-standalone/argp-standalone/configure 8 | deps/argp-standalone/argp-standalone/stamp-h1 9 | deps/argp-standalone/argp-standalone/testsuite/Makefile 10 | # deps/argp-standalone/argp-standalone/testsuite/Makefile.in 11 | deps/bc-bip39/Makefile 12 | deps/bc-bip39/config.guess 13 | deps/bc-bip39/config.h 14 | deps/bc-bip39/config.log 15 | deps/bc-bip39/config.status 16 | deps/bc-bip39/config.sub 17 | deps/bc-bip39/configure 18 | deps/bc-bip39/src/Makefile 19 | deps/bc-bip39/test/Makefile 20 | deps/bc-crypto-base/Makefile 21 | deps/bc-crypto-base/config.guess 22 | deps/bc-crypto-base/config.h 23 | deps/bc-crypto-base/config.log 24 | deps/bc-crypto-base/config.status 25 | deps/bc-crypto-base/config.sub 26 | deps/bc-crypto-base/configure 27 | deps/bc-crypto-base/src/Makefile 28 | deps/bc-crypto-base/test/Makefile 29 | deps/bc-shamir/Makefile 30 | deps/bc-shamir/config.guess 31 | deps/bc-shamir/config.h 32 | deps/bc-shamir/config.log 33 | deps/bc-shamir/config.status 34 | deps/bc-shamir/config.sub 35 | deps/bc-shamir/configure 36 | deps/bc-shamir/src/Makefile 37 | deps/bc-shamir/test/Makefile 38 | deps/bc-sskr/Makefile 39 | deps/bc-sskr/config.guess 40 | deps/bc-sskr/config.h 41 | deps/bc-sskr/config.log 42 | deps/bc-sskr/config.status 43 | deps/bc-sskr/config.sub 44 | deps/bc-sskr/configure 45 | deps/bc-sskr/src/Makefile 46 | deps/bc-sskr/test/Makefile 47 | deps/bc-ur/Makefile 48 | deps/bc-ur/config.guess 49 | deps/bc-ur/config.h 50 | deps/bc-ur/config.log 51 | deps/bc-ur/config.status 52 | deps/bc-ur/config.sub 53 | deps/bc-ur/configure 54 | deps/bc-ur/src/Makefile 55 | deps/bc-ur/test/Makefile 56 | config.log 57 | config.status 58 | src/Makefile 59 | src/config.h 60 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: seedtool-cli 2 | Section: unknown 3 | Priority: optional 4 | Maintainer: Wolf McNally 5 | Rules-Requires-Root: no 6 | Build-Depends: 7 | debhelper-compat (= 13), 8 | autotools-dev, 9 | Standards-Version: 4.6.1 10 | Homepage: https://github.com/BlockchainCommons/seedtool-cli 11 | #Vcs-Browser: https://salsa.debian.org/debian/seedtool-cli 12 | Vcs-Git: https://github.com/BlockchainCommons/seedtool-cli.git 13 | 14 | Package: seedtool-cli 15 | Architecture: any 16 | Depends: 17 | ${shlibs:Depends}, 18 | ${misc:Depends}, 19 | Description: A command-line tool for creating and transforming cryptographic seeds of the sort commonly used by blockchain applications. 20 | 21 | 22 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Source: 3 | Upstream-Name: seedtool-cli 4 | Upstream-Contact: 5 | 6 | Files: 7 | * 8 | Copyright: 9 | 10 | 11 | License: 12 | 13 | 14 | . 15 | 16 | 17 | # If you want to use GPL v2 or later for the /debian/* files use 18 | # the following clauses, or change it to suit. Delete these two lines 19 | Files: 20 | debian/* 21 | Copyright: 22 | 2023 unknown 23 | License: GPL-2+ 24 | This package is free software; you can redistribute it and/or modify 25 | it under the terms of the GNU General Public License as published by 26 | the Free Software Foundation; either version 2 of the License, or 27 | (at your option) any later version. 28 | . 29 | This package is distributed in the hope that it will be useful, 30 | but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 | GNU General Public License for more details. 33 | . 34 | You should have received a copy of the GNU General Public License 35 | along with this program. If not, see 36 | Comment: 37 | On Debian systems, the complete text of the GNU General 38 | Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". 39 | 40 | # Please also look if there are files or directories which have a 41 | # different copyright/license attached and list them here. 42 | # Please avoid picking licenses with terms that are more restrictive than the 43 | # packaged work, as it may make Debian's contributions unacceptable upstream. 44 | # 45 | # If you need, there are some extra license texts available in two places: 46 | # /usr/share/debhelper/dh_make/licenses/ 47 | # /usr/share/common-licenses/ 48 | -------------------------------------------------------------------------------- /debian/manpage.1.ex: -------------------------------------------------------------------------------- 1 | .\" Hey, EMACS: -*- nroff -*- 2 | .\" (C) Copyright 2023 unknown , 3 | .\" 4 | .\" First parameter, NAME, should be all caps 5 | .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection 6 | .\" other parameters are allowed: see man(7), man(1) 7 | .TH Seedtool-cli SECTION "February 6 2023" 8 | .\" Please adjust this date whenever revising the manpage. 9 | .\" 10 | .\" Some roff macros, for reference: 11 | .\" .nh disable hyphenation 12 | .\" .hy enable hyphenation 13 | .\" .ad l left justify 14 | .\" .ad b justify to both left and right margins 15 | .\" .nf disable filling 16 | .\" .fi enable filling 17 | .\" .br insert line break 18 | .\" .sp insert n+1 empty lines 19 | .\" for manpage-specific macros, see man(7) 20 | .SH NAME 21 | seedtool-cli \- program to do something 22 | .SH SYNOPSIS 23 | .B seedtool-cli 24 | .RI [ options ] " files" ... 25 | .br 26 | .B bar 27 | .RI [ options ] " files" ... 28 | .SH DESCRIPTION 29 | This manual page documents briefly the 30 | .B seedtool-cli 31 | and 32 | .B bar 33 | commands. 34 | .PP 35 | .\" TeX users may be more comfortable with the \fB\fP and 36 | .\" \fI\fP escape sequences to invode bold face and italics, 37 | .\" respectively. 38 | \fBseedtool-cli\fP is a program that... 39 | .SH OPTIONS 40 | These programs follow the usual GNU command line syntax, with long 41 | options starting with two dashes ('\-'). 42 | A summary of options is included below. 43 | For a complete description, see the Info files. 44 | .TP 45 | .B \-h, \-\-help 46 | Show summary of options. 47 | .TP 48 | .B \-v, \-\-version 49 | Show version of program. 50 | .SH SEE ALSO 51 | .BR bar (1), 52 | .BR baz (1). 53 | .br 54 | The programs are documented fully by 55 | .IR "The Rise and Fall of a Fooish Bar" , 56 | available via the Info system. 57 | -------------------------------------------------------------------------------- /debian/manpage.md.ex: -------------------------------------------------------------------------------- 1 | % seedtool-cli(SECTION) | User Commands 2 | % 3 | % "February 6 2023" 4 | 5 | [comment]: # The lines above form a Pandoc metadata block. They must be 6 | [comment]: # the first ones in the file. 7 | [comment]: # See https://pandoc.org/MANUAL.html#metadata-blocks for details. 8 | 9 | [comment]: # pandoc -s -f markdown -t man package.md -o package.1 10 | [comment]: # 11 | [comment]: # A manual page package.1 will be generated. You may view the 12 | [comment]: # manual page with: nroff -man package.1 | less. A typical entry 13 | [comment]: # in a Makefile or Makefile.am is: 14 | [comment]: # 15 | [comment]: # package.1: package.md 16 | [comment]: # pandoc --standalone --from=markdown --to=man $< --output=$@ 17 | [comment]: # 18 | [comment]: # The pandoc binary is found in the pandoc package. Please remember 19 | [comment]: # that if you create the nroff version in one of the debian/rules 20 | [comment]: # file targets, such as build, you will need to include pandoc in 21 | [comment]: # your Build-Depends control field. 22 | 23 | [comment]: # Remove the lines starting with '[comment]:' in this file in order 24 | [comment]: # to avoid warning messages from pandoc. 25 | 26 | # NAME 27 | 28 | seedtool-cli - program to do something 29 | 30 | # SYNOPSIS 31 | 32 | **seedtool-cli** **-e** _this_ [**\-\-example=that**] [{**-e** | **\-\-example**} _this_] 33 | [{**-e** | **\-\-example**} {_this_ | _that_}] 34 | 35 | **seedtool-cli** [{**-h** | *\-\-help**} | {**-v** | **\-\-version**}] 36 | 37 | # DESCRIPTION 38 | 39 | This manual page documents briefly the **seedtool-cli** and **bar** commands. 40 | 41 | This manual page was written for the Debian distribution because the 42 | original program does not have a manual page. Instead, it has documentation 43 | in the GNU info(1) format; see below. 44 | 45 | **seedtool-cli** is a program that... 46 | 47 | # OPTIONS 48 | 49 | The program follows the usual GNU command line syntax, with long options 50 | starting with two dashes ('-'). A summary of options is included below. For 51 | a complete description, see the **info**(1) files. 52 | 53 | **-e** _this_, **\-\-example=**_that_ 54 | : Does this and that. 55 | 56 | **-h**, **\-\-help** 57 | : Show summary of options. 58 | 59 | **-v**, **\-\-version** 60 | : Show version of program. 61 | 62 | # FILES 63 | 64 | /etc/foo.conf 65 | : The system-wide configuration file to control the behaviour of 66 | seedtool-cli. See **foo.conf**(5) for further details. 67 | 68 | ${HOME}/.foo.conf 69 | : The per-user configuration file to control the behaviour of 70 | seedtool-cli. See **foo.conf**(5) for further details. 71 | 72 | # ENVIRONMENT 73 | 74 | **FOO_CONF** 75 | : If used, the defined file is used as configuration file (see also 76 | the section called “FILES”). 77 | 78 | # DIAGNOSTICS 79 | 80 | The following diagnostics may be issued on stderr: 81 | 82 | Bad configuration file. Exiting. 83 | : The configuration file seems to contain a broken configuration 84 | line. Use the **\-\-verbose** option, to get more info. 85 | 86 | **seedtool-cli** provides some return codes, that can be used in scripts: 87 | 88 | Code Diagnostic 89 | 0 Program exited successfully. 90 | 1 The configuration file seems to be broken. 91 | 92 | # BUGS 93 | 94 | The program is currently limited to only work with the foobar library. 95 | 96 | The upstream BTS can be found at http://bugzilla.foo.tld. 97 | 98 | # SEE ALSO 99 | 100 | **bar**(1), **baz**(1), **foo.conf**(5) 101 | 102 | The programs are documented fully by The Rise and Fall of a Fooish Bar 103 | available via the **info**(1) system. 104 | 105 | # AUTHOR 106 | 107 | unknown 108 | : Wrote this manpage for the Debian system. 109 | 110 | # COPYRIGHT 111 | 112 | Copyright © 2007 unknown 113 | 114 | This manual page was written for the Debian system (and may be used by 115 | others). 116 | 117 | Permission is granted to copy, distribute and/or modify this document under 118 | the terms of the GNU General Public License, Version 2 or (at your option) 119 | any later version published by the Free Software Foundation. 120 | 121 | On Debian systems, the complete text of the GNU General Public License 122 | can be found in /usr/share/common-licenses/GPL. 123 | 124 | [comment]: # Local Variables: 125 | [comment]: # mode: markdown 126 | [comment]: # End: 127 | -------------------------------------------------------------------------------- /debian/manpage.sgml.ex: -------------------------------------------------------------------------------- 1 | manpage.1'. You may view 5 | the manual page with: 'docbook-to-man manpage.sgml | nroff -man | 6 | less'. A typical entry in a Makefile or Makefile.am is: 7 | 8 | manpage.1: manpage.sgml 9 | docbook-to-man $< > $@ 10 | 11 | 12 | The docbook-to-man binary is found in the docbook-to-man package. 13 | Please remember that if you create the nroff version in one of the 14 | debian/rules file targets (such as build), you will need to include 15 | docbook-to-man in your Build-Depends control field. 16 | 17 | --> 18 | 19 | 20 | FIRSTNAME"> 21 | SURNAME"> 22 | 23 | February 6 2023"> 24 | 26 | SECTION"> 27 | nik@unknown"> 28 | 29 | Seedtool-cli"> 30 | 31 | 32 | Debian"> 33 | GNU"> 34 | GPL"> 35 | ]> 36 | 37 | 38 | 39 |
40 | &dhemail; 41 |
42 | 43 | &dhfirstname; 44 | &dhsurname; 45 | 46 | 47 | 2003 48 | &dhusername; 49 | 50 | &dhdate; 51 |
52 | 53 | &dhucpackage; 54 | 55 | &dhsection; 56 | 57 | 58 | &dhpackage; 59 | 60 | program to do something 61 | 62 | 63 | 64 | &dhpackage; 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | DESCRIPTION 73 | 74 | This manual page documents briefly the 75 | &dhpackage; and bar 76 | commands. 77 | 78 | This manual page was written for the &debian; distribution 79 | because the original program does not have a manual page. 80 | Instead, it has documentation in the &gnu; 81 | Info format; see below. 82 | 83 | &dhpackage; is a program that... 84 | 85 | 86 | 87 | OPTIONS 88 | 89 | These programs follow the usual &gnu; command line syntax, 90 | with long options starting with two dashes ('-'). A summary of 91 | options is included below. For a complete description, see the 92 | Info files. 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | Show summary of options. 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | Show version of program. 109 | 110 | 111 | 112 | 113 | 114 | SEE ALSO 115 | 116 | bar (1), baz (1). 117 | 118 | The programs are documented fully by The Rise and 119 | Fall of a Fooish Bar available via the 120 | Info system. 121 | 122 | 123 | AUTHOR 124 | 125 | This manual page was written by &dhusername; &dhemail; for 126 | the &debian; system (and may be used by others). Permission is 127 | granted to copy, distribute and/or modify this document under 128 | the terms of the &gnu; General Public License, Version 2 any 129 | later version published by the Free Software Foundation. 130 | 131 | 132 | On Debian systems, the complete text of the GNU General Public 133 | License can be found in /usr/share/common-licenses/GPL. 134 | 135 | 136 | 137 |
138 | 139 | 155 | -------------------------------------------------------------------------------- /debian/manpage.xml.ex: -------------------------------------------------------------------------------- 1 | 2 | .
will be generated. You may view the 15 | manual page with: nroff -man .
| less'. A typical entry 16 | in a Makefile or Makefile.am is: 17 | 18 | DB2MAN = /usr/share/sgml/docbook/stylesheet/xsl/docbook-xsl/manpages/docbook.xsl 19 | XP = xsltproc -''-nonet -''-param man.charmap.use.subset "0" 20 | 21 | manpage.1: manpage.xml 22 | $(XP) $(DB2MAN) $< 23 | 24 | The xsltproc binary is found in the xsltproc package. The XSL files are in 25 | docbook-xsl. A description of the parameters you can use can be found in the 26 | docbook-xsl-doc-* packages. Please remember that if you create the nroff 27 | version in one of the debian/rules file targets (such as build), you will need 28 | to include xsltproc and docbook-xsl in your Build-Depends control field. 29 | Alternatively use the xmlto command/package. That will also automatically 30 | pull in xsltproc and docbook-xsl. 31 | 32 | Notes for using docbook2x: docbook2x-man does not automatically create the 33 | AUTHOR(S) and COPYRIGHT sections. In this case, please add them manually as 34 | ... . 35 | 36 | To disable the automatic creation of the AUTHOR(S) and COPYRIGHT sections 37 | read /usr/share/doc/docbook-xsl/doc/manpages/authors.html. This file can be 38 | found in the docbook-xsl-doc-html package. 39 | 40 | Validation can be done using: `xmllint -''-noout -''-valid manpage.xml` 41 | 42 | General documentation about man-pages and man-page-formatting: 43 | man(1), man(7), http://www.tldp.org/HOWTO/Man-Page/ 44 | 45 | --> 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 56 | 57 | 59 | 60 | 61 | 62 | ]> 63 | 64 | 65 | 66 | &dhtitle; 67 | &dhpackage; 68 | 69 | 70 | &dhfirstname; 71 | &dhsurname; 72 | Wrote this manpage for the Debian system. 73 |
74 | &dhemail; 75 |
76 |
77 |
78 | 79 | 2007 80 | &dhusername; 81 | 82 | 83 | This manual page was written for the Debian system 84 | (and may be used by others). 85 | Permission is granted to copy, distribute and/or modify this 86 | document under the terms of the GNU General Public License, 87 | Version 2 or (at your option) any later version published by 88 | the Free Software Foundation. 89 | On Debian systems, the complete text of the GNU General Public 90 | License can be found in 91 | /usr/share/common-licenses/GPL. 92 | 93 |
94 | 95 | &dhucpackage; 96 | &dhsection; 97 | 98 | 99 | &dhpackage; 100 | program to do something 101 | 102 | 103 | 104 | &dhpackage; 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | this 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | this 122 | that 123 | 124 | 125 | 126 | 127 | &dhpackage; 128 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | DESCRIPTION 148 | This manual page documents briefly the 149 | &dhpackage; and bar 150 | commands. 151 | This manual page was written for the Debian distribution 152 | because the original program does not have a manual page. 153 | Instead, it has documentation in the GNU 154 | info 155 | 1 156 | format; see below. 157 | &dhpackage; is a program that... 158 | 159 | 160 | OPTIONS 161 | The program follows the usual GNU command line syntax, 162 | with long options starting with two dashes ('-'). A summary of 163 | options is included below. For a complete description, see the 164 | 165 | info 166 | 1 167 | files. 168 | 169 | 172 | 173 | 174 | 175 | 176 | Does this and that. 177 | 178 | 179 | 180 | 181 | 182 | 183 | Show summary of options. 184 | 185 | 186 | 187 | 188 | 189 | 190 | Show version of program. 191 | 192 | 193 | 194 | 195 | 196 | FILES 197 | 198 | 199 | /etc/foo.conf 200 | 201 | The system-wide configuration file to control the 202 | behaviour of &dhpackage;. See 203 | 204 | foo.conf 205 | 5 206 | for further details. 207 | 208 | 209 | 210 | ${HOME}/.foo.conf 211 | 212 | The per-user configuration file to control the 213 | behaviour of &dhpackage;. See 214 | 215 | foo.conf 216 | 5 217 | for further details. 218 | 219 | 220 | 221 | 222 | 223 | ENVIRONMENT 224 | 225 | 226 | FOO_CONF 227 | 228 | If used, the defined file is used as configuration 229 | file (see also ). 230 | 231 | 232 | 233 | 234 | 235 | DIAGNOSTICS 236 | The following diagnostics may be issued 237 | on stderr: 238 | 239 | 240 | Bad configuration file. Exiting. 241 | 242 | The configuration file seems to contain a broken configuration 243 | line. Use the option, to get more info. 244 | 245 | 246 | 247 | 248 | &dhpackage; provides some return codes, that can 249 | be used in scripts: 250 | 251 | Code 252 | Diagnostic 253 | 254 | 0 255 | Program exited successfully. 256 | 257 | 258 | 1 259 | The configuration file seems to be broken. 260 | 261 | 262 | 263 | 264 | 265 | BUGS 266 | The program is currently limited to only work 267 | with the foobar library. 268 | The upstreams BTS can be found 269 | at . 270 | 271 | 272 | SEE ALSO 273 | 274 | 275 | bar 276 | 1 277 | , 278 | baz 279 | 1 280 | , 281 | foo.conf 282 | 5 283 | 284 | The programs are documented fully by The Rise and 285 | Fall of a Fooish Bar available via the 286 | info 287 | 1 288 | system. 289 | 290 |
291 | 292 | -------------------------------------------------------------------------------- /debian/patches/series: -------------------------------------------------------------------------------- 1 | fix-build.diff 2 | fix-build.0.diff 3 | Makefile.diff 4 | -------------------------------------------------------------------------------- /debian/postinst.ex: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postinst script for seedtool-cli. 3 | # 4 | # See: dh_installdeb(1). 5 | 6 | set -e 7 | 8 | # Summary of how this script can be called: 9 | # * 'configure' 10 | # * 'abort-upgrade' 11 | # * 'abort-remove' 'in-favour' 12 | # 13 | # * 'abort-remove' 14 | # * 'abort-deconfigure' 'in-favour' 15 | # 'removing' 16 | # 17 | # for details, see https://www.debian.org/doc/debian-policy/ or 18 | # the debian-policy package. 19 | 20 | 21 | case "$1" in 22 | configure) 23 | ;; 24 | 25 | abort-upgrade|abort-remove|abort-deconfigure) 26 | ;; 27 | 28 | *) 29 | echo "postinst called with unknown argument '$1'" >&2 30 | exit 1 31 | ;; 32 | esac 33 | 34 | # dh_installdeb will replace this with shell code automatically 35 | # generated by other debhelper scripts. 36 | 37 | #DEBHELPER# 38 | 39 | exit 0 40 | -------------------------------------------------------------------------------- /debian/postrm.ex: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postrm script for seedtool-cli. 3 | # 4 | # See: dh_installdeb(1). 5 | 6 | set -e 7 | 8 | # Summary of how this script can be called: 9 | # * 'remove' 10 | # * 'purge' 11 | # * 'upgrade' 12 | # * 'failed-upgrade' 13 | # * 'abort-install' 14 | # * 'abort-install' 15 | # * 'abort-upgrade' 16 | # * 'disappear' 17 | # 18 | # for details, see https://www.debian.org/doc/debian-policy/ or 19 | # the debian-policy package. 20 | 21 | 22 | case "$1" in 23 | purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) 24 | ;; 25 | 26 | *) 27 | echo "postrm called with unknown argument '$1'" >&2 28 | exit 1 29 | ;; 30 | esac 31 | 32 | # dh_installdeb will replace this with shell code automatically 33 | # generated by other debhelper scripts. 34 | 35 | #DEBHELPER# 36 | 37 | exit 0 38 | -------------------------------------------------------------------------------- /debian/preinst.ex: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # preinst script for seedtool-cli. 3 | # 4 | # See: dh_installdeb(1). 5 | 6 | set -e 7 | 8 | # Summary of how this script can be called: 9 | # * 'install' 10 | # * 'install' 11 | # * 'upgrade' 12 | # * 'abort-upgrade' 13 | # for details, see https://www.debian.org/doc/debian-policy/ or 14 | # the debian-policy package. 15 | 16 | 17 | case "$1" in 18 | install|upgrade) 19 | ;; 20 | 21 | abort-upgrade) 22 | ;; 23 | 24 | *) 25 | echo "preinst called with unknown argument '$1'" >&2 26 | exit 1 27 | ;; 28 | esac 29 | 30 | # dh_installdeb will replace this with shell code automatically 31 | # generated by other debhelper scripts. 32 | 33 | #DEBHELPER# 34 | 35 | exit 0 36 | -------------------------------------------------------------------------------- /debian/prerm.ex: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # prerm script for seedtool-cli. 3 | # 4 | # See: dh_installdeb(1). 5 | 6 | set -e 7 | 8 | # Summary of how this script can be called: 9 | # * 'remove' 10 | # * 'upgrade' 11 | # * 'failed-upgrade' 12 | # * 'remove' 'in-favour' 13 | # * 'deconfigure' 'in-favour' 14 | # 'removing' 15 | # 16 | # for details, see https://www.debian.org/doc/debian-policy/ or 17 | # the debian-policy package. 18 | 19 | 20 | case "$1" in 21 | remove|upgrade|deconfigure) 22 | ;; 23 | 24 | failed-upgrade) 25 | ;; 26 | 27 | *) 28 | echo "prerm called with unknown argument '$1'" >&2 29 | exit 1 30 | ;; 31 | esac 32 | 33 | # dh_installdeb will replace this with shell code automatically 34 | # generated by other debhelper scripts. 35 | 36 | #DEBHELPER# 37 | 38 | exit 0 39 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | # See debhelper(7) (uncomment to enable). 4 | # Output every command that modifies files on the build system. 5 | #export DH_VERBOSE = 1 6 | 7 | # See FEATURE AREAS in dpkg-buildflags(1). 8 | #export DEB_BUILD_MAINT_OPTIONS = hardening=+all 9 | 10 | # See ENVIRONMENT in dpkg-buildflags(1). 11 | # Package maintainers to append CFLAGS. 12 | #export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic 13 | # Package maintainers to append LDFLAGS. 14 | #export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed 15 | 16 | export CC=clang 17 | export CXX=clang++ 18 | export SYSROOT=/tmp/sysroot 19 | export LIB=${SYSROOT}/lib 20 | export INCLUDE=${SYSROOT}/include 21 | 22 | export CFLAGS += -I${INCLUDE} 23 | export CXXFLAGS += -I${INCLUDE} 24 | export LDFLAGS += -L${LIB} 25 | 26 | %: 27 | cd deps/bc-crypto-base && \ 28 | autoreconf --install && \ 29 | ./configure --prefix ${SYSROOT} && \ 30 | make check && \ 31 | make install && make clean || true 32 | 33 | cd deps/bc-shamir && \ 34 | autoreconf --install && \ 35 | ./configure --prefix ${SYSROOT} && \ 36 | make check && \ 37 | make install && make clean || true 38 | 39 | cd deps/bc-sskr && \ 40 | autoreconf --install && \ 41 | ./configure --prefix ${SYSROOT} && \ 42 | make check && \ 43 | make install && make clean || true 44 | 45 | cd deps/bc-bip39 && \ 46 | autoreconf --install && \ 47 | ./configure --prefix ${SYSROOT} && \ 48 | make check && \ 49 | make install && make clean || true 50 | 51 | cd deps/bc-ur && \ 52 | autoreconf --install && \ 53 | ./configure --prefix ${SYSROOT} && \ 54 | make check && \ 55 | make install && make clean || true 56 | 57 | cd deps/argp-standalone/argp-standalone && \ 58 | autoreconf --install && \ 59 | ./configure --prefix ${SYSROOT} && \ 60 | make install && \ 61 | cp libargp.a ${SYSROOT}/lib/ && \ 62 | cp argp.h ${SYSROOT}/include/ && \ 63 | make distclean 64 | 65 | dh $@ 66 | 67 | override_dh_autoreconf: 68 | autoreconf --install 69 | dh_autoreconf 70 | 71 | # dh_make generated override targets. 72 | # This is an example for Cmake (see ). 73 | # override_dh_auto_configure: 74 | # ./configure 75 | 76 | # override_dh_auto_build: 77 | # dh_auto_build 78 | 79 | # override_dh_auto_test: 80 | # dh_auto_test 81 | 82 | override_dh_auto_clean: 83 | cd deps/bc-crypto-base && make clean || true 84 | cd deps/bc-shamir && make clean || true 85 | cd deps/bc-sskr && make clean || true 86 | cd deps/bc-bip39 && make clean || true 87 | cd deps/bc-ur && make clean || true 88 | cd deps/argp-standalone/argp-standalone && make clean || true 89 | if [ -f ./Makefile ];then make distclean; fi 90 | # TEST that this clears old copies of source/seedtool 91 | # dh_auto_clean 92 | 93 | override_dh_dwz: 94 | true 95 | -------------------------------------------------------------------------------- /debian/salsa-ci.yml.ex: -------------------------------------------------------------------------------- 1 | # For more information on what jobs are run see: 2 | # https://salsa.debian.org/salsa-ci-team/pipeline 3 | # 4 | # To enable the jobs, go to your repository (at salsa.debian.org) 5 | # and click over Settings > CI/CD > Expand (in General pipelines). 6 | # In "CI/CD configuration file" write debian/salsa-ci.yml and click 7 | # in "Save Changes". The CI tests will run after the next commit. 8 | --- 9 | include: 10 | - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml 11 | - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml 12 | -------------------------------------------------------------------------------- /debian/seedtool-cli-docs.docs: -------------------------------------------------------------------------------- 1 | README.source 2 | README.Debian 3 | -------------------------------------------------------------------------------- /debian/seedtool-cli.cron.d.ex: -------------------------------------------------------------------------------- 1 | # 2 | # Regular cron jobs for the seedtool-cli package. 3 | # 4 | 0 4 * * * root [ -x /usr/bin/seedtool-cli_maintenance ] && /usr/bin/seedtool-cli_maintenance 5 | -------------------------------------------------------------------------------- /debian/seedtool-cli.doc-base.ex: -------------------------------------------------------------------------------- 1 | Document: seedtool-cli 2 | Title: Debian seedtool-cli Manual 3 | Author: 4 | Abstract: This manual describes what seedtool-cli is 5 | and how it can be used to 6 | manage online manuals on Debian systems. 7 | Section: unknown 8 | 9 | Format: debiandoc-sgml 10 | Files: /usr/share/doc/seedtool-cli/seedtool-cli.sgml.gz 11 | 12 | Format: postscript 13 | Files: /usr/share/doc/seedtool-cli/seedtool-cli.ps.gz 14 | 15 | Format: text 16 | Files: /usr/share/doc/seedtool-cli/seedtool-cli.text.gz 17 | 18 | Format: HTML 19 | Index: /usr/share/doc/seedtool-cli/html/index.html 20 | Files: /usr/share/doc/seedtool-cli/html/*.html 21 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/source/include-binaries: -------------------------------------------------------------------------------- 1 | src/format-base10.o 2 | src/format-base6.o 3 | src/format-bip39.o 4 | src/format-bits.o 5 | src/format-bytewords-minimal.o 6 | src/format-bytewords-uri.o 7 | src/format-bytewords.o 8 | src/format-cards.o 9 | src/format-dice.o 10 | src/format-hex.o 11 | src/format-ints.o 12 | src/format-random.o 13 | src/format-sskr.o 14 | src/format.o 15 | src/hkdf.o 16 | src/params.o 17 | src/random.o 18 | src/randombytes.o 19 | src/seedtool 20 | src/seedtool.o 21 | src/utils.o 22 | -------------------------------------------------------------------------------- /debian/source/options: -------------------------------------------------------------------------------- 1 | # This, when put here, doesn't work. 2 | # extend-diff-ignore = "(/deps/.*)|(/src/Makefile.in)|(/debian/)$" 3 | extend-diff-ignore = "packaging.md" 4 | extend-diff-ignore = "build/.*" 5 | # extend-diff-ignore = "deps/.*" 6 | extend-diff-ignore = "src/config.h.in" 7 | extend-diff-ignore = "build-tailsOS.Dockerfile" 8 | extend-diff-ignore = "stamp-h1" 9 | extend-diff-ignore = "configure" 10 | extend-diff-ignore = "test.log" 11 | extend-diff-ignore = "test/Makefile" 12 | extend-diff-ignore = "testsuite/Makefile" 13 | # skip-patches -------------------------------------------------------------------------------- /debian/upstream/metadata.ex: -------------------------------------------------------------------------------- 1 | # Example file for upstream/metadata. 2 | # See https://wiki.debian.org/UpstreamMetadata for more info/fields. 3 | # Below an example based on a github project. 4 | 5 | # Bug-Database: https://github.com//seedtool-cli/issues 6 | # Bug-Submit: https://github.com//seedtool-cli/issues/new 7 | # Changelog: https://github.com//seedtool-cli/blob/master/CHANGES 8 | # Documentation: https://github.com//seedtool-cli/wiki 9 | # Repository-Browse: https://github.com//seedtool-cli 10 | # Repository: https://github.com//seedtool-cli.git 11 | -------------------------------------------------------------------------------- /debian/watch.ex: -------------------------------------------------------------------------------- 1 | # Example watch control file for uscan. 2 | # Rename this file to "watch" and then you can run the "uscan" command 3 | # to check for upstream updates and more. 4 | # See uscan(1) for format. 5 | 6 | # Compulsory line, this is a version 4 file. 7 | version=4 8 | 9 | # PGP signature mangle, so foo.tar.gz has foo.tar.gz.sig. 10 | #opts="pgpsigurlmangle=s%$%.sig%" 11 | 12 | # HTTP site (basic). 13 | #http://example.com/downloads.html \ 14 | # files/seedtool-cli-([\d\.]+)\.tar\.gz 15 | 16 | # Uncomment to examine an FTP server. 17 | #ftp://ftp.example.com/pub/seedtool-cli-(.*)\.tar\.gz 18 | 19 | # SourceForge hosted projects. 20 | #http://sf.net/seedtool-cli/ seedtool-cli-(.*)\.tar\.gz 21 | 22 | # GitHub hosted projects. 23 | #opts="filenamemangle=s%(?:.*?)?v?(@ANY_VERSION@@ARCHIVE_EXT@)%@PACKAGE@-$1%" \ 24 | # https://github.com///tags \ 25 | # (?:.*?/)v?@ANY_VERSION@@ARCHIVE_EXT@ 26 | 27 | # GitLab hosted projects. 28 | #opts="filenamemangle=s%(?:.*?)?v?(@ANY_VERSION@@ARCHIVE_EXT@)%@PACKAGE@-$1%" \ 29 | # https://gitlab.com///-/tags \ 30 | # archive/v?@ANY_VERSION@/-v?\d\S*@ARCHIVE_EXT@ 31 | 32 | # PyPI. 33 | #https://pypi.debian.net/seedtool-cli/seedtool-cli-(.+)\.(?:zip|tgz|tbz|txz|(?:tar\.(?:gz|bz2|xz))) 34 | 35 | # Direct Git. 36 | #opts="mode=git" http://git.example.com/seedtool-cli.git \ 37 | # refs/tags/v([\d\.]+) 38 | -------------------------------------------------------------------------------- /example-scripts/bip39-to-sskr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # This is an example script that uses Seedtool that converts a BIP39 seed into a set of SSKR shares in one step. 5 | # 6 | # 7 | # Example invocation on single line: 8 | # 9 | # ./bip39-to-sskr.sh "slender horse coil sketch public wink nest point royal believe inform lyrics critic harbor scheme enrich burden glance song chicken grief first panic actor" --group-threshold 1 --group 2-of-3 --group 3-of-5 10 | # 11 | # tuna acid epic hard data tied visa acid acid able hope glow iced meow flew ruby omit fizz need task gear claw door hope meow waxy dark keep barn math beta tent half wasp idea fern peck void limp peck fact half cook game down fish 12 | # tuna acid epic hard data tied visa acid acid acid keno kept oboe data rock skew plus vast free kick horn horn fund foxy tomb gray diet soap roof runs time pose yell able inch fern crux lung into twin pool back user purr fish guru 13 | # tuna acid epic hard data tied visa acid acid also belt fish yurt wave play gear ruby claw fern redo cola wave waxy iron blue luau film bulb kept taco pose drop bias dull jowl fern open echo heat game axis waxy jury list king judo 14 | # tuna acid epic hard data tied visa acid brag able drop mild paid what rich fair jolt urge user exit race saga lion user play cyan crux heat fizz wolf figs chef oval void half numb king gems puma exam away oval scar play vibe cook 15 | # tuna acid epic hard data tied visa acid brag acid cyan axis mild trip fizz unit dice calm memo ramp flew sets toil trip view waxy mild days lung news gush diet yank yank back pool aunt scar roof draw even zest many rust axis memo 16 | # tuna acid epic hard data tied visa acid brag also menu noon flux lamb quiz gift lazy slot twin very axis high hope ruby aqua surf acid very rich each knob fund purr guru oboe mint flux pool fizz gear sets apex deli kiwi tent bald 17 | # tuna acid epic hard data tied visa acid brag apex next also knob hang gift play slot bias miss jowl zone heat barn road game acid quiz next jury holy cash keys very flap zone monk fish curl gift good zaps hawk jade calm fern list 18 | # tuna acid epic hard data tied visa acid brag aqua work cyan cash onyx cook inch fern memo note sets wall need soap puff cusp free eyes crux grim code solo lamb judo veto main idle days cusp solo zest kiwi quad foxy claw play unit 19 | # 20 | # 21 | # Example invocation using STDIN to supply the BIP39 words 22 | # 23 | # ./bip39-to-sskr.sh "" --group-threshold 1 --group 2-of-3 --group 3-of-5 24 | # slender horse coil sketch public wink nest point royal believe inform lyrics critic harbor scheme enrich burden glance song chicken grief first panic actor 25 | # ^D 26 | # 27 | # tuna acid epic hard data skew wand acid acid able jugs noon kiln aunt roof leaf race figs horn exit knob wave next fuel pose taco miss work ruby webs huts film mild wolf zoom free puff wave whiz sets beta wave tent time kiwi vibe 28 | # tuna acid epic hard data skew wand acid acid acid hill oboe lazy stub hard fair diet days task jowl glow jade hope into hope undo game toys view flux vibe navy time judo duty main eyes hope junk what news lazy redo half yank gyro 29 | # tuna acid epic hard data skew wand acid acid also diet visa miss liar jowl warm mint bald data mint code zaps also aunt gush wand even purr belt plus judo join chef waxy kiln soap rich memo warm plus each epic task numb unit kept 30 | # tuna acid epic hard data skew wand acid brag able leaf wall toys trip undo exit ruby navy girl work legs bulb purr luau girl wasp poem quiz able void skew puff yawn gyro kite rich cook each peck belt lazy time void luck zaps maze 31 | # tuna acid epic hard data skew wand acid brag acid yoga jolt gems song mild hard inky when zest keep surf work hard news calm gear poem plus zone cook numb lava leaf work judo ruin zinc oval task next acid gyro oboe road lion runs 32 | # tuna acid epic hard data skew wand acid brag also high runs memo onyx note skew good jury oval peck pose menu toil lung news note iris hard slot kite arch navy heat note tent high item very barn limp zone quad taxi judo fuel eyes 33 | # tuna acid epic hard data skew wand acid brag apex days exit axis ramp tomb oval luau cost bulb down vast junk fish navy sets exit iris fizz eyes limp idea peck drum film unit help loud keno iron buzz knob epic mild frog fair cash 34 | # tuna acid epic hard data skew wand acid brag aqua lung grim visa help echo deli into ruby webs glow data item wand deli iced memo arch door buzz chef into toys ruin numb user wall idle echo half zest work tiny tied pose apex vibe 35 | # 36 | 37 | BIP39=$1 38 | SSKR_OPTIONS=${@:2} 39 | seedtool --in bip39 ${BIP39} | seedtool --in hex --out sskr ${SSKR_OPTIONS} 40 | -------------------------------------------------------------------------------- /example-scripts/sskr-to-bip39.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # This is an example script that converts a set of SSKR shares to BIP-39 seed in one step. It takes the shares from STDIN and 5 | # write the BIP-39 seed to STDOUT. 6 | # 7 | # Example invocation: 8 | # 9 | # ./sskr-to-bip39.sh 10 | # tuna acid epic hard data tied visa acid acid able hope glow iced meow flew ruby omit fizz need task gear claw door hope meow waxy dark keep barn math beta tent half wasp idea fern peck void limp peck fact half cook game down fish 11 | # tuna acid epic hard data tied visa acid acid acid keno kept oboe data rock skew plus vast free kick horn horn fund foxy tomb gray diet soap roof runs time pose yell able inch fern crux lung into twin pool back user purr fish guru 12 | # ^D 13 | # 14 | # slender horse coil sketch public wink nest point royal believe inform lyrics critic harbor scheme enrich burden glance song chicken grief first panic actor 15 | 16 | seedtool --in sskr | seedtool --in hex --out bip39 17 | -------------------------------------------------------------------------------- /images/logos/README.md: -------------------------------------------------------------------------------- 1 | Logos for social media. 2 | -------------------------------------------------------------------------------- /images/logos/seedtool-logo-black.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-logo-black.jpg -------------------------------------------------------------------------------- /images/logos/seedtool-logo-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-logo-black.png -------------------------------------------------------------------------------- /images/logos/seedtool-logo-black.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-logo-black.psd -------------------------------------------------------------------------------- /images/logos/seedtool-logo-shapes.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-logo-shapes.ai -------------------------------------------------------------------------------- /images/logos/seedtool-logo-white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-logo-white.jpg -------------------------------------------------------------------------------- /images/logos/seedtool-logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-logo-white.png -------------------------------------------------------------------------------- /images/logos/seedtool-logo-white.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-logo-white.psd -------------------------------------------------------------------------------- /images/logos/seedtool-screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-screen.jpg -------------------------------------------------------------------------------- /images/logos/seedtool-screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-screen.png -------------------------------------------------------------------------------- /images/logos/seedtool-screen.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/images/logos/seedtool-screen.psd -------------------------------------------------------------------------------- /manual-images/seedqrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BlockchainCommons/seedtool-cli/b79d02fb6d936921dd36c08c3994bfd155ee7288/manual-images/seedqrcode.png -------------------------------------------------------------------------------- /set_build_paths.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SYSROOT=${PWD}/sysroot 4 | LIB=${SYSROOT}/lib 5 | INCLUDE=${SYSROOT}/include 6 | 7 | export CFLAGS="${CFLAGS} -I${INCLUDE}" 8 | export CXXFLAGS="${CXXFLAGS} -I${INCLUDE}" 9 | export LDFLAGS="${LDFLAGS} -L${LIB}" 10 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | seedtool 2 | -------------------------------------------------------------------------------- /src/Makefile.in: -------------------------------------------------------------------------------- 1 | # @configure_input@ 2 | 3 | # 4 | # Makefile.in 5 | # 6 | # Copyright © 2020 by Blockchain Commons, LLC 7 | # Licensed under the "BSD-2-Clause Plus Patent License" 8 | # 9 | 10 | # Package-specific substitution variables 11 | package = @PACKAGE_NAME@ 12 | version = @PACKAGE_VERSION@ 13 | tarname = @PACKAGE_TARNAME@ 14 | 15 | # Prefix-specific substitution variables 16 | prefix = @prefix@ 17 | exec_prefix = @exec_prefix@ 18 | bindir = @bindir@ 19 | 20 | # VPATH-specific substitution variables 21 | srcdir = @srcdir@ 22 | VPATH = @srcdir@ 23 | 24 | # Terminal colors 25 | RED=`tput setaf 1` 26 | GREEN=`tput setaf 2` 27 | RESET=`tput sgr0` 28 | 29 | CBOR_DIR = ../deps/cbor-lite 30 | 31 | COMPILER = g++ 32 | CFLAGS += --debug -O0 33 | CXXFLAGS += -std=c++17 --debug -O0 -I"$(CBOR_DIR)/include" 34 | 35 | toolname = seedtool 36 | 37 | .PHONY: all 38 | all: $(toolname) 39 | 40 | OBJS = \ 41 | seedtool.o \ 42 | utils.o \ 43 | params.o \ 44 | random.o \ 45 | format.o \ 46 | format-base6.o \ 47 | format-base10.o \ 48 | format-bip39.o \ 49 | format-bits.o \ 50 | format-cards.o \ 51 | format-dice.o \ 52 | format-hex.o \ 53 | format-ints.o \ 54 | format-random.o \ 55 | format-sskr.o \ 56 | format-bytewords.o \ 57 | format-bytewords-uri.o \ 58 | format-bytewords-minimal.o \ 59 | randombytes.o \ 60 | hkdf.o 61 | 62 | LDLIBS += -lbc-sskr -lbc-shamir -lbc-crypto-base -lbc-bip39 -lbc-ur -largp 63 | 64 | UNAME := $(shell uname) 65 | ifeq ($(UNAME), Linux) 66 | LDLIBS += -lm -lgcc_s -lgcc -lstdc++ 67 | else ifeq ($(findstring MINGW64, $(UNAME)), MINGW64) 68 | # on windows building with msys2/mingw64 69 | LDLIBS += -lm -lc++ -lws2_32 70 | else 71 | LDLIBS += -lstdc++ 72 | endif 73 | 74 | $(toolname): $(OBJS) 75 | 76 | seedtool.o: params.hpp format.hpp 77 | utils.o: utils.hpp 78 | params.o: params.hpp utils.hpp random.hpp formats-all.hpp config.h 79 | random.o: random.hpp randombytes.h hkdf.h utils.hpp 80 | randombytes.o: randombytes.h 81 | hkdf.o: hkdf.h 82 | format.o: format.hpp utils.hpp 83 | formats-all.hpp: format-base6.hpp format-base10.hpp format-bip39.hpp format-bits.hpp format-cards.hpp format-dice.hpp format-hex.hpp format-ints.hpp format-random.hpp format-sskr.hpp format-bytewords.hpp format-bytewords-uri.hpp format-bytewords-minimal.hpp 84 | format-base6.o: format-base6.hpp format.hpp params.hpp random.hpp 85 | format-base10.o: format-base10.hpp format.hpp params.hpp random.hpp 86 | format-bip39.o: format-bip39.hpp format.hpp params.hpp random.hpp utils.hpp cbor-utils.hpp 87 | format-bits.o: format-bits.hpp format.hpp params.hpp random.hpp 88 | format-cards.o: format-cards.hpp format.hpp params.hpp random.hpp 89 | format-dice.o: format-dice.hpp format.hpp params.hpp random.hpp 90 | format-hex.o: format-hex.hpp format.hpp params.hpp random.hpp utils.hpp cbor-utils.hpp 91 | format-ints.o: format-ints.hpp format.hpp params.hpp random.hpp 92 | format-random.o: format-random.hpp format.hpp params.hpp random.hpp 93 | format-sskr.o: format-sskr.hpp format.hpp params.hpp random.hpp utils.hpp cbor-utils.hpp 94 | format-bytewords.o: format-bytewords.hpp format.hpp params.hpp random.hpp 95 | format-bytewords-uri.o: format-bytewords-uri.hpp format.hpp params.hpp random.hpp 96 | format-bytewords-minimal.o: format-bytewords-minimal.hpp format.hpp params.hpp random.hpp 97 | 98 | bindir = $(DESTDIR)$(prefix)/bin 99 | 100 | .PHONY: install 101 | install: $(toolname) 102 | install -d $(bindir) 103 | install $(toolname) $(bindir) 104 | 105 | .PHONY: uninstall 106 | uninstall: 107 | rm -f $(bindir)/$(toolname) 108 | -rmdir $(bindir) >/dev/null 2>&1 109 | 110 | .PHONY: check 111 | check: $(toolname) 112 | ./test.sh ./$(toolname) 113 | 114 | .PHONY: clean 115 | clean: 116 | rm -f $(toolname) *.o 117 | rm -rf *.dSYM 118 | 119 | .PHONY: distclean 120 | distclean: clean 121 | rm -f Makefile 122 | rm -f config.h 123 | 124 | .PHONY: lint 125 | lint: 126 | cppcheck --enable=all --error-exitcode=1 --inline-suppr --suppress=missingInclude --suppress=ConfigurationNotChecked . 127 | -------------------------------------------------------------------------------- /src/cbor-utils.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // cbor.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #ifndef CBOR_UTILS_HPP 9 | #define CBOR_UTILS_HPP 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "utils.hpp" 17 | 18 | const auto cborDecodingFlags = ur::CborLite::Flag::requireMinimalEncoding; 19 | 20 | template 21 | void encode_byte_string(Buffer& cbor, const ByteVector& bytes) { 22 | ur::CborLite::encodeBytes(cbor, bytes); 23 | } 24 | 25 | template 26 | void decode_byte_string(Iter& pos, Iter end, ByteVector& bytes) { 27 | ur::CborLite::decodeBytes(pos, end, bytes, cborDecodingFlags); 28 | } 29 | 30 | template 31 | void encode_string_array(Buffer& cbor, const StringVector& strings) { 32 | ur::CborLite::encodeArraySize(cbor, strings.size()); 33 | for(auto string: strings) { 34 | ur::CborLite::encodeText(cbor, string); 35 | } 36 | } 37 | 38 | template 39 | void decode_string_array(Iter& pos, Iter end, StringVector& strings) { 40 | size_t size; 41 | ur::CborLite::decodeArraySize(pos, end, size, cborDecodingFlags); 42 | for(auto i = 0; i < size; i++) { 43 | std::string s; 44 | ur::CborLite::decodeText(pos, end, s, cborDecodingFlags); 45 | strings.push_back(s); 46 | } 47 | } 48 | 49 | template 50 | void encode_array_of_string_arrays(Buffer& cbor, const std::vector& array_of_string_arrays) { 51 | ur::CborLite::encodeArraySize(cbor, array_of_string_arrays.size()); 52 | for(auto string_array: array_of_string_arrays) { 53 | encode_string_array(cbor, string_array); 54 | } 55 | } 56 | 57 | template 58 | void decode_array_of_string_arrays(Iter& pos, Iter end, std::vector& array_of_string_arrays) { 59 | size_t size; 60 | ur::CborLite::decodeArraySize(pos, end, size, cborDecodingFlags); 61 | for(auto i = 0; i < size; i++) { 62 | StringVector strings; 63 | decode_string_array(pos, end, strings); 64 | array_of_string_arrays.push_back(strings); 65 | } 66 | } 67 | 68 | template 69 | void encode_dict_with_birthdate(Buffer& cbor, const ByteVector& embedded_cbor, bool include_birthdate) { 70 | size_t map_size = include_birthdate ? 2 : 1; 71 | ur::CborLite::encodeMapSize(cbor, size_t(map_size)); 72 | ur::CborLite::encodeInteger(cbor, 1); 73 | append(cbor, embedded_cbor); 74 | if(include_birthdate) { 75 | ur::CborLite::encodeInteger(cbor, 2); 76 | ur::CborLite::encodeTagAndValue(cbor, ur::CborLite::Major::semantic, size_t(100)); 77 | ur::CborLite::encodeInteger(cbor, days_since_epoch()); 78 | } 79 | } 80 | 81 | template 82 | void decode_dict_with_birthdate(Iter& pos, Iter end, Func f) { 83 | size_t map_len; 84 | auto len = ur::CborLite::decodeMapSize(pos, end, map_len, cborDecodingFlags); 85 | std::set labels; 86 | for(auto i = 0; i < map_len; i++) { 87 | int label; 88 | ur::CborLite::decodeInteger(pos, end, label, cborDecodingFlags); 89 | if(labels.find(label) != labels.end()) { 90 | throw std::runtime_error("Duplicate label."); 91 | } 92 | labels.insert(label); 93 | switch (label) { 94 | case 1: 95 | f(pos, end); 96 | break; 97 | case 2: { 98 | // Birthday field ignored 99 | ur::CborLite::Tag tag; 100 | size_t value; 101 | ur::CborLite::decodeTagAndValue(pos, end, tag, value, cborDecodingFlags); 102 | if(tag != ur::CborLite::Major::semantic) { 103 | throw std::runtime_error("Invalid date."); 104 | } 105 | switch(value) { 106 | case 0: { 107 | std::string date; 108 | ur::CborLite::decodeText(pos, end, date, cborDecodingFlags); 109 | } 110 | break; 111 | case 1: { 112 | double date; 113 | ur::CborLite::decodeDoubleFloat(pos, end, date, cborDecodingFlags); 114 | } 115 | break; 116 | case 100: { 117 | int date; 118 | ur::CborLite::decodeInteger(pos, end, date, cborDecodingFlags); 119 | } 120 | break; 121 | default: 122 | throw std::runtime_error("Invalid date."); 123 | } 124 | } 125 | break; 126 | case 3: { 127 | // Name field ignored 128 | std::string name; 129 | ur::CborLite::decodeText(pos, end, name, cborDecodingFlags); 130 | } 131 | break; 132 | case 4: { 133 | // Note field ignored 134 | std::string note; 135 | ur::CborLite::decodeText(pos, end, note, cborDecodingFlags); 136 | } 137 | break; 138 | default: 139 | throw std::runtime_error("Unknown label."); 140 | break; 141 | } 142 | } 143 | if(pos != end) { 144 | throw std::runtime_error("Additional unknown bytes at end."); 145 | } 146 | } 147 | 148 | #endif // CBOR_UTILS_HPP 149 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | /* src/config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define to 1 if you have the header file. */ 4 | #undef HAVE_FCNTL_H 5 | 6 | /* Define to 1 if you have the header file. */ 7 | #undef HAVE_INTTYPES_H 8 | 9 | /* Define to 1 if you have the `argp' library (-largp). */ 10 | #undef HAVE_LIBARGP 11 | 12 | /* Define to 1 if you have the `bc-bip39' library (-lbc-bip39). */ 13 | #undef HAVE_LIBBC_BIP39 14 | 15 | /* Define to 1 if you have the `bc-crypto-base' library (-lbc-crypto-base). */ 16 | #undef HAVE_LIBBC_CRYPTO_BASE 17 | 18 | /* Define to 1 if you have the `bc-shamir' library (-lbc-shamir). */ 19 | #undef HAVE_LIBBC_SHAMIR 20 | 21 | /* Define to 1 if you have the `bc-sskr' library (-lbc-sskr). */ 22 | #undef HAVE_LIBBC_SSKR 23 | 24 | /* Define to 1 if you have the `bc-ur' library (-lbc-ur). */ 25 | #undef HAVE_LIBBC_UR 26 | 27 | /* Define to 1 if your system has a GNU libc compatible `malloc' function, and 28 | to 0 otherwise. */ 29 | #undef HAVE_MALLOC 30 | 31 | /* Define to 1 if you have the header file. */ 32 | #undef HAVE_MEMORY_H 33 | 34 | /* Define to 1 if you have the `memset' function. */ 35 | #undef HAVE_MEMSET 36 | 37 | /* Define to 1 if you have the header file. */ 38 | #undef HAVE_STDDEF_H 39 | 40 | /* Define to 1 if you have the header file. */ 41 | #undef HAVE_STDINT_H 42 | 43 | /* Define to 1 if you have the header file. */ 44 | #undef HAVE_STDIO_H 45 | 46 | /* Define to 1 if you have the header file. */ 47 | #undef HAVE_STDLIB_H 48 | 49 | /* Define to 1 if you have the `strerror' function. */ 50 | #undef HAVE_STRERROR 51 | 52 | /* Define to 1 if you have the header file. */ 53 | #undef HAVE_STRINGS_H 54 | 55 | /* Define to 1 if you have the header file. */ 56 | #undef HAVE_STRING_H 57 | 58 | /* Define to 1 if you have the header file. */ 59 | #undef HAVE_SYS_IOCTL_H 60 | 61 | /* Define to 1 if you have the header file. */ 62 | #undef HAVE_SYS_PARAM_H 63 | 64 | /* Define to 1 if you have the header file. */ 65 | #undef HAVE_SYS_STAT_H 66 | 67 | /* Define to 1 if you have the header file. */ 68 | #undef HAVE_SYS_TYPES_H 69 | 70 | /* Define to 1 if you have the header file. */ 71 | #undef HAVE_UNISTD_H 72 | 73 | /* Define to 1 if the system has the type `_Bool'. */ 74 | #undef HAVE__BOOL 75 | 76 | /* Define to the address where bug reports for this package should be sent. */ 77 | #undef PACKAGE_BUGREPORT 78 | 79 | /* Define to the full name of this package. */ 80 | #undef PACKAGE_NAME 81 | 82 | /* Define to the full name and version of this package. */ 83 | #undef PACKAGE_STRING 84 | 85 | /* Define to the one symbol short name of this package. */ 86 | #undef PACKAGE_TARNAME 87 | 88 | /* Define to the home page for this package. */ 89 | #undef PACKAGE_URL 90 | 91 | /* Define to the version of this package. */ 92 | #undef PACKAGE_VERSION 93 | 94 | /* Define to 1 if all of the C90 standard headers exist (not just the ones 95 | required in a freestanding environment). This macro is provided for 96 | backward compatibility; new code need not use it. */ 97 | #undef STDC_HEADERS 98 | 99 | /* Define for Solaris 2.5.1 so the uint32_t typedef from , 100 | , or is not used. If the typedef were allowed, the 101 | #define below would cause a syntax error. */ 102 | #undef _UINT32_T 103 | 104 | /* Define for Solaris 2.5.1 so the uint64_t typedef from , 105 | , or is not used. If the typedef were allowed, the 106 | #define below would cause a syntax error. */ 107 | #undef _UINT64_T 108 | 109 | /* Define for Solaris 2.5.1 so the uint8_t typedef from , 110 | , or is not used. If the typedef were allowed, the 111 | #define below would cause a syntax error. */ 112 | #undef _UINT8_T 113 | 114 | /* Define to `__inline__' or `__inline' if that's what the C compiler 115 | calls it, or to nothing if 'inline' is not supported under any name. */ 116 | #ifndef __cplusplus 117 | #undef inline 118 | #endif 119 | 120 | /* Define to the type of a signed integer type of width exactly 16 bits if 121 | such a type exists and the standard includes do not define it. */ 122 | #undef int16_t 123 | 124 | /* Define to the type of a signed integer type of width exactly 32 bits if 125 | such a type exists and the standard includes do not define it. */ 126 | #undef int32_t 127 | 128 | /* Define to rpl_malloc if the replacement function should be used. */ 129 | #undef malloc 130 | 131 | /* Define to `unsigned int' if does not define. */ 132 | #undef size_t 133 | 134 | /* Define to `int' if does not define. */ 135 | #undef ssize_t 136 | 137 | /* Define to the type of an unsigned integer type of width exactly 16 bits if 138 | such a type exists and the standard includes do not define it. */ 139 | #undef uint16_t 140 | 141 | /* Define to the type of an unsigned integer type of width exactly 32 bits if 142 | such a type exists and the standard includes do not define it. */ 143 | #undef uint32_t 144 | 145 | /* Define to the type of an unsigned integer type of width exactly 64 bits if 146 | such a type exists and the standard includes do not define it. */ 147 | #undef uint64_t 148 | 149 | /* Define to the type of an unsigned integer type of width exactly 8 bits if 150 | such a type exists and the standard includes do not define it. */ 151 | #undef uint8_t 152 | -------------------------------------------------------------------------------- /src/format-base10.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-base10.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-base10.hpp" 9 | 10 | #include 11 | 12 | #include "params.hpp" 13 | #include "utils.hpp" 14 | #include "random.hpp" 15 | 16 | void FormatBase10::process_input(Params* p) { 17 | auto input = p->get_one_argument(); 18 | 19 | #if 0 20 | auto entropy = digits_to_data(input, 0, 9); 21 | p->seed = deterministic_random(entropy, p->count); 22 | #else 23 | // Compatibility with https://iancoleman.io/bip39/ 24 | digits_to_data(input, 0, 9); // syntax check only 25 | p->seed = sha256_deterministic_random(input, p->count); 26 | #endif 27 | } 28 | 29 | void FormatBase10::process_output(Params* p) { 30 | p->output = data_to_ints(p->seed, 0, 9, ""); 31 | } 32 | -------------------------------------------------------------------------------- /src/format-base10.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-base10.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatBase10 : public Format { 13 | public: 14 | FormatBase10() : Format(Format::Key::base10, "base10") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | }; 19 | -------------------------------------------------------------------------------- /src/format-base6.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-base6.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-base6.hpp" 9 | 10 | #include 11 | 12 | #include "params.hpp" 13 | #include "utils.hpp" 14 | #include "random.hpp" 15 | 16 | void FormatBase6::process_input(Params* p) { 17 | auto input = p->get_one_argument(); 18 | 19 | #if 0 20 | auto entropy = digits_to_data(input, 0, 5); 21 | p->seed = deterministic_random(entropy, p->count); 22 | #else 23 | // Compatibility with https://iancoleman.io/bip39/ 24 | digits_to_data(input, 0, 5); // syntax check only 25 | p->seed = sha256_deterministic_random(input, p->count); 26 | #endif 27 | } 28 | 29 | void FormatBase6::process_output(Params* p) { 30 | p->output = data_to_ints(p->seed, 0, 5, ""); 31 | } 32 | -------------------------------------------------------------------------------- /src/format-base6.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-base6.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatBase6 : public Format { 13 | public: 14 | FormatBase6() : Format(Format::Key::base6, "base6") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | }; 19 | -------------------------------------------------------------------------------- /src/format-bip39.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bip39.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-bip39.hpp" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include "params.hpp" 17 | #include "utils.hpp" 18 | #include "cbor-utils.hpp" 19 | 20 | using namespace std; 21 | 22 | bool FormatBIP39::is_seed_length_valid(size_t seed_len) { 23 | if(!(12 <= seed_len && seed_len <= 32)) { return false; } 24 | if(seed_len % 4 != 0) { return false; } 25 | return true; 26 | } 27 | 28 | void FormatBIP39::process_input(Params* p) { 29 | string input; 30 | 31 | if(p->is_ur_in) { 32 | auto& ur = p->ur_shares.front(); 33 | auto pos = ur.cbor().begin(); 34 | const auto end = ur.cbor().end(); 35 | 36 | StringVector strings; 37 | typedef ur::ByteVector::const_iterator Iter; 38 | auto f = [&strings](Iter& pos, Iter end) { 39 | decode_string_array(pos, end, strings); 40 | }; 41 | decode_dict_with_birthdate(pos, end, f); 42 | input = join(strings, " "); 43 | } else { 44 | input = p->get_combined_arguments(); 45 | } 46 | 47 | ByteVector buf; 48 | buf.resize(300); 49 | auto len = bip39_secret_from_mnemonics(input.c_str(), buf.data(), buf.size()); 50 | if(len == 0) { 51 | throw runtime_error("Invalid BIP39 word sequence."); 52 | } 53 | buf.resize(len); 54 | p->seed = buf; 55 | } 56 | 57 | void FormatBIP39::process_output(Params* p) { 58 | if(!is_seed_length_valid(p->seed.size())) { 59 | throw runtime_error("Invalid seed length for BIP39. Must be in [12-32] and divisible by 4."); 60 | } 61 | 62 | size_t max_mnemonics_len = 300; 63 | char mnemonics[max_mnemonics_len]; 64 | bip39_mnemonics_from_secret(p->seed.data(), p->seed.size(), mnemonics, max_mnemonics_len); 65 | string s = mnemonics; 66 | 67 | if(p->is_ur_out) { 68 | auto words = split(s, ' '); 69 | ByteVector encoded_words; 70 | encode_string_array(encoded_words, words); 71 | ByteVector dict; 72 | encode_dict_with_birthdate(dict, encoded_words, false); 73 | p->set_ur_output(dict, "crypto-bip39"); 74 | } else { 75 | p->output = s; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/format-bip39.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bip39.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatBIP39 : public Format { 13 | public: 14 | FormatBIP39() : Format(Format::Key::bip39, "bip39") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | 19 | static bool is_seed_length_valid(size_t seed_len); 20 | }; 21 | -------------------------------------------------------------------------------- /src/format-bits.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bits.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-bits.hpp" 9 | 10 | #include 11 | 12 | #include "params.hpp" 13 | #include "utils.hpp" 14 | #include "random.hpp" 15 | 16 | void FormatBits::process_input(Params* p) { 17 | auto input = p->get_one_argument(); 18 | 19 | #if 0 20 | auto entropy = digits_to_data(input, 0, 1); 21 | p->seed = deterministic_random(entropy, p->count); 22 | #else 23 | // Compatibility with https://iancoleman.io/bip39/ 24 | digits_to_data(input, 0, 1); // syntax check only 25 | p->seed = sha256_deterministic_random(input, p->count); 26 | #endif 27 | } 28 | 29 | void FormatBits::process_output(Params* p) { 30 | p->output = data_to_ints(p->seed, 0, 1, ""); 31 | } 32 | -------------------------------------------------------------------------------- /src/format-bits.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bits.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatBits : public Format { 13 | public: 14 | FormatBits() : Format(Format::Key::bits, "bits") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | }; 19 | -------------------------------------------------------------------------------- /src/format-bytewords-minimal.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bytewords.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-bytewords-minimal.hpp" 9 | 10 | #include 11 | #include 12 | 13 | #include "params.hpp" 14 | #include "utils.hpp" 15 | 16 | using namespace std; 17 | 18 | bool FormatBytewordsMinimal::is_seed_length_valid(size_t seed_len) { 19 | if(!(1 <= seed_len && seed_len <= 64)) { return false; } 20 | return true; 21 | } 22 | 23 | void FormatBytewordsMinimal::process_input(Params* p) { 24 | auto input = p->get_one_argument(); 25 | p->seed = ur::Bytewords::decode(ur::Bytewords::style::minimal, input); 26 | } 27 | 28 | void FormatBytewordsMinimal::process_output(Params* p) { 29 | p->output = ur::Bytewords::encode(ur::Bytewords::style::minimal, p->seed); 30 | } 31 | -------------------------------------------------------------------------------- /src/format-bytewords-minimal.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bch32.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatBytewordsMinimal : public Format { 13 | public: 14 | FormatBytewordsMinimal() : Format(Format::Key::bytewords, "bytewords") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | 19 | static bool is_seed_length_valid(size_t seed_len); 20 | }; 21 | -------------------------------------------------------------------------------- /src/format-bytewords-uri.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bytewords.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-bytewords-uri.hpp" 9 | 10 | #include 11 | #include 12 | 13 | #include "params.hpp" 14 | #include "utils.hpp" 15 | 16 | using namespace std; 17 | 18 | bool FormatBytewordsURI::is_seed_length_valid(size_t seed_len) { 19 | if(!(1 <= seed_len && seed_len <= 64)) { return false; } 20 | return true; 21 | } 22 | 23 | void FormatBytewordsURI::process_input(Params* p) { 24 | auto input = p->get_one_argument(); 25 | p->seed = ur::Bytewords::decode(ur::Bytewords::style::uri, input); 26 | } 27 | 28 | void FormatBytewordsURI::process_output(Params* p) { 29 | p->output = ur::Bytewords::encode(ur::Bytewords::style::uri, p->seed); 30 | } 31 | -------------------------------------------------------------------------------- /src/format-bytewords-uri.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bch32.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatBytewordsURI : public Format { 13 | public: 14 | FormatBytewordsURI() : Format(Format::Key::bytewords, "bytewords") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | 19 | static bool is_seed_length_valid(size_t seed_len); 20 | }; 21 | -------------------------------------------------------------------------------- /src/format-bytewords.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bytewords.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-bytewords.hpp" 9 | 10 | #include 11 | #include 12 | 13 | #include "params.hpp" 14 | #include "utils.hpp" 15 | 16 | using namespace std; 17 | 18 | bool FormatBytewords::is_seed_length_valid(size_t seed_len) { 19 | if(!(1 <= seed_len && seed_len <= 64)) { return false; } 20 | return true; 21 | } 22 | 23 | void FormatBytewords::process_input(Params* p) { 24 | auto input = p->get_one_argument(); 25 | p->seed = ur::Bytewords::decode(ur::Bytewords::style::standard, input); 26 | } 27 | 28 | void FormatBytewords::process_output(Params* p) { 29 | p->output = ur::Bytewords::encode(ur::Bytewords::style::standard, p->seed); 30 | } 31 | -------------------------------------------------------------------------------- /src/format-bytewords.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-bch32.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatBytewords : public Format { 13 | public: 14 | FormatBytewords() : Format(Format::Key::bytewords, "bytewords") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | 19 | static bool is_seed_length_valid(size_t seed_len); 20 | }; 21 | -------------------------------------------------------------------------------- /src/format-cards.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-cards.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-cards.hpp" 9 | 10 | #include 11 | #include 12 | 13 | #include "params.hpp" 14 | #include "utils.hpp" 15 | #include "random.hpp" 16 | 17 | using namespace std; 18 | 19 | // Arrangement of cards per: 20 | // https://github.com/iancoleman/bip39/blob/master/src/js/entropy.js 21 | static const string card_suits = "cdhs"; 22 | static const string card_ranks = "a23456789tjqk"; 23 | 24 | static size_t parse_rank(char c) { 25 | c = tolower(c); 26 | for(size_t i = 0; i < card_ranks.size(); i++) { 27 | if(c == card_ranks[i]) { 28 | return i; 29 | } 30 | } 31 | throw runtime_error("Invalid card rank. Allowed: [A,2-9,T,J,Q,K]"); 32 | } 33 | 34 | static size_t parse_suit(char c) { 35 | c = tolower(c); 36 | for(size_t i = 0; i < card_suits.size(); i++) { 37 | if(c == card_suits[i]) { 38 | return i; 39 | } 40 | } 41 | throw runtime_error("Invalid card rank. Allowed: [D,C,H,S]"); 42 | } 43 | 44 | ByteVector cards_to_data(const string& cards) { 45 | ByteVector result; 46 | 47 | auto len = cards.length(); 48 | if(len % 2 != 0) { 49 | throw runtime_error("Cards string must have even number of characters."); 50 | } 51 | auto count = len / 2; 52 | result.reserve(count); 53 | for(auto i = 0; i < count; i++) { 54 | auto rank = parse_rank(cards[i * 2]); 55 | auto suit = parse_suit(cards[i * 2 + 1]); 56 | auto n = suit * 13 + rank; 57 | result.push_back(n); 58 | } 59 | 60 | return result; 61 | } 62 | 63 | void FormatCards::process_input(Params* p) { 64 | auto input = p->get_one_argument(); 65 | 66 | // NOT currently compatible with with https://iancoleman.io/bip39/ 67 | // https://github.com/iancoleman/bip39/blob/54600393af3293dc9e0f222b24ebd07b63824330/src/js/entropy.js#L245 68 | 69 | auto entropy = cards_to_data(input); 70 | p->seed = deterministic_random(entropy, p->count); 71 | } 72 | 73 | static string to_card(size_t n) { 74 | if(n > 51) { return NULL; } 75 | string buf; 76 | size_t rank = n % 13; 77 | size_t suit = n / 13; 78 | buf += card_ranks[rank]; 79 | buf += card_suits[suit]; 80 | 81 | // test value round trip 82 | auto v = cards_to_data(buf); 83 | assert(v.size() == 1); 84 | assert(v[0] == n); 85 | 86 | return buf; 87 | } 88 | 89 | void FormatCards::process_output(Params* p) { 90 | p->output = data_to_alphabet(p->seed, 52, to_card); 91 | } 92 | -------------------------------------------------------------------------------- /src/format-cards.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-cards.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatCards : public Format { 13 | public: 14 | FormatCards() : Format(Format::Key::cards, "cards") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | }; 19 | -------------------------------------------------------------------------------- /src/format-dice.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-dice.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-dice.hpp" 9 | #include "params.hpp" 10 | #include "utils.hpp" 11 | #include "random.hpp" 12 | 13 | void FormatDice::process_input(Params* p) { 14 | auto input = p->get_one_argument(); 15 | 16 | #if 0 17 | auto entropy = digits_to_data(input, 1, 6); 18 | p->seed = deterministic_random(entropy, p->count); 19 | #else 20 | // Compatibility with https://iancoleman.io/bip39/ 21 | digits_to_data(input, 1, 6); // syntax check only 22 | p->seed = sha256_deterministic_random(input, p->count); 23 | #endif 24 | } 25 | 26 | void FormatDice::process_output(Params* p) { 27 | p->output = data_to_ints(p->seed, 1, 6, ""); 28 | } 29 | -------------------------------------------------------------------------------- /src/format-dice.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-dice.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatDice : public Format { 13 | public: 14 | FormatDice() : Format(Format::Key::dice, "dice") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | }; 19 | -------------------------------------------------------------------------------- /src/format-hex.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-hex.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-hex.hpp" 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include "params.hpp" 17 | #include "utils.hpp" 18 | #include "cbor-utils.hpp" 19 | 20 | using namespace std; 21 | 22 | void FormatHex::process_input(Params* p) { 23 | 24 | // Currently compatible with with https://iancoleman.io/bip39/ 25 | // ONLY in "raw entropy" mode. 26 | 27 | if(p->is_ur_in) { 28 | auto& ur = p->ur_shares.front(); 29 | auto pos = ur.cbor().begin(); 30 | const auto end = ur.cbor().end(); 31 | 32 | ByteVector bytes; 33 | typedef ur::ByteVector::const_iterator Iter; 34 | auto f = [&bytes](Iter& pos, Iter end) { 35 | decode_byte_string(pos, end, bytes); 36 | }; 37 | decode_dict_with_birthdate(pos, end, f); 38 | 39 | p->seed = bytes; 40 | } else { 41 | auto input = p->get_one_argument(); 42 | p->seed = hex_to_data(input); 43 | } 44 | } 45 | 46 | void FormatHex::process_output(Params* p) { 47 | if(p->is_ur_out) { 48 | ByteVector byte_string; 49 | encode_byte_string(byte_string, p->seed); 50 | ByteVector dict; 51 | encode_dict_with_birthdate(dict, byte_string, false); 52 | p->set_ur_output(dict, "seed"); 53 | } else { 54 | p->output = data_to_hex(p->seed); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/format-hex.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-hex.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatHex : public Format { 13 | public: 14 | FormatHex() : Format(Format::Key::hex, "hex") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | }; 19 | -------------------------------------------------------------------------------- /src/format-ints.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-ints.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-ints.hpp" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "params.hpp" 16 | #include "utils.hpp" 17 | #include "random.hpp" 18 | 19 | using namespace std; 20 | 21 | FormatInts::FormatInts() : Format(Format::Key::ints, "ints") { 22 | low = 0; 23 | high = 9; 24 | } 25 | 26 | static ByteVector parse_ints(const string& input) { 27 | ByteVector result; 28 | 29 | istringstream iss(input); 30 | 31 | while(!iss.eof()) { 32 | string s; 33 | iss >> s; 34 | int i; 35 | if(!(stringstream(s) >> i)) { 36 | throw runtime_error("Invalid integer. Allowed: [0-255]"); 37 | } 38 | if(!(0 <= i && i <= 255)) { 39 | throw runtime_error("Integer out of range. Allowed: [0-255]"); 40 | } 41 | result.push_back(i); 42 | } 43 | 44 | return result; 45 | } 46 | 47 | void FormatInts::process_input(Params* p) { 48 | auto input = p->get_combined_arguments(); 49 | auto entropy = parse_ints(input); 50 | p->seed = deterministic_random(entropy, p->count); 51 | } 52 | 53 | void FormatInts::process_output(Params* p) { 54 | p->output = data_to_ints(p->seed, low, high, " "); 55 | } 56 | -------------------------------------------------------------------------------- /src/format-ints.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-ints.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatInts : public Format { 13 | public: 14 | FormatInts(); 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | 19 | size_t low; 20 | size_t high; 21 | }; 22 | -------------------------------------------------------------------------------- /src/format-random.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-random.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-random.hpp" 9 | #include "params.hpp" 10 | 11 | void FormatRandom::process_input(Params* p) { 12 | p->seed.resize(p->count); 13 | p->rng(p->seed.data(), p->count, NULL); 14 | } 15 | 16 | void FormatRandom::process_output(Params* p) { 17 | assert(false); // never happens 18 | } 19 | -------------------------------------------------------------------------------- /src/format-random.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-random.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format.hpp" 11 | 12 | class FormatRandom : public Format { 13 | public: 14 | FormatRandom() : Format(Format::Key::random, "random") {} 15 | 16 | virtual void process_input(Params* p) override; 17 | virtual void process_output(Params* p) override; 18 | }; 19 | -------------------------------------------------------------------------------- /src/format-sskr.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-sskr.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format-sskr.hpp" 9 | 10 | #include 11 | #include 12 | 13 | #include "params.hpp" 14 | #include "cbor-utils.hpp" 15 | #include 16 | 17 | using namespace std; 18 | 19 | bool FormatSSKR::is_seed_length_valid(size_t seed_len) { 20 | if(!(16 <= seed_len && seed_len <= 32)) { return false; } 21 | if(seed_len % 2 != 0) { return false; } 22 | return true; 23 | } 24 | 25 | static ByteVector combine(StringVector shares) { 26 | vector shares_bytes; 27 | size_t bytes_in_each_share = 0; 28 | for(auto share: shares) { 29 | auto cbor_buf = ur::Bytewords::decode(ur::Bytewords::standard, share); 30 | auto pos = cbor_buf.begin(); 31 | auto end = cbor_buf.end(); 32 | 33 | ur::CborLite::Tag tag; 34 | size_t value; 35 | ur::CborLite::decodeTagAndValue(pos, end, tag, value, ur::CborLite::Flag::requireMinimalEncoding); 36 | if(tag != ur::CborLite::Major::semantic || value != 309) { 37 | throw runtime_error("Not a valid SSKR share."); 38 | } 39 | ByteVector* bytes_buf = new ByteVector; 40 | ur::CborLite::decodeBytes(pos, end, *bytes_buf, ur::CborLite::Flag::requireMinimalEncoding); 41 | auto bytes_in_share = bytes_buf->size(); 42 | if(bytes_in_each_share == 0) { 43 | bytes_in_each_share = bytes_in_share; 44 | } else if(bytes_in_share != bytes_in_each_share) { 45 | throw runtime_error("SSKR shares do not all have equal numbers of words."); 46 | } 47 | shares_bytes.push_back(bytes_buf); 48 | } 49 | 50 | vector shares_bytes_pointers; 51 | for(const auto v: shares_bytes) { 52 | auto p = v->data(); 53 | shares_bytes_pointers.push_back(p); 54 | } 55 | 56 | size_t result_len = bytes_in_each_share - METADATA_LENGTH_BYTES; 57 | ByteVector result(result_len) ; 58 | 59 | auto recovered_secret_len = sskr_combine( 60 | shares_bytes_pointers.data(), bytes_in_each_share, shares_bytes_pointers.size(), 61 | result.data(), result.size() 62 | ); 63 | 64 | if(recovered_secret_len != result_len) { 65 | throw runtime_error("Invalid SSKR shares."); 66 | } 67 | 68 | for(auto p: shares_bytes) { 69 | delete p; 70 | } 71 | 72 | return result; 73 | } 74 | 75 | void FormatSSKR::process_input(Params* p) { 76 | if(p->is_ur_in) { 77 | for(auto& ur: p->ur_shares) { 78 | auto bw = ur::Bytewords::encode(ur::Bytewords::standard, ur.cbor()); 79 | p->shares.push_back(bw); 80 | } 81 | } else { 82 | p->shares = p->get_multiple_arguments(); 83 | } 84 | p->seed = combine(p->shares); 85 | } 86 | 87 | void FormatSSKR::process_output(Params* p) { 88 | // If we received a UR in and the input method was also SSKR, the actual 89 | // contained shares have been extracted in process_input() above, so we simply 90 | // output them. 91 | if(p->is_ur_in && !p->shares.empty()) { 92 | p->output = join(p->shares, "\n"); 93 | return; 94 | } 95 | 96 | auto seed_len = p->seed.size(); 97 | auto share_len = seed_len + METADATA_LENGTH_BYTES; 98 | auto share_count = sskr_count_shards(groups_threshold, groups.data(), groups.size()); 99 | auto shares_buffer_len = share_len * share_count; 100 | 101 | if(!is_seed_length_valid(seed_len)) { 102 | throw runtime_error("Invalid seed length for SSKR. Must be in [16-32] and even."); 103 | } 104 | 105 | size_t bytes_in_each_share = 0; 106 | uint8_t shares_buffer[shares_buffer_len]; 107 | 108 | int gen_share_count = sskr_generate( 109 | groups_threshold, groups.data(), groups.size(), 110 | p->seed.data(), seed_len, 111 | &bytes_in_each_share, shares_buffer, shares_buffer_len, 112 | NULL, 113 | p->rng 114 | ); 115 | 116 | assert(gen_share_count == share_count); 117 | assert(bytes_in_each_share == share_len); 118 | 119 | if(p->is_ur_out) { 120 | StringVector strings; 121 | for (int i = 0; i < share_count; i++) { 122 | uint8_t* bytes = shares_buffer + (i * bytes_in_each_share); 123 | auto v = ByteVector(bytes, bytes + bytes_in_each_share); 124 | ByteVector cbor; 125 | ur::CborLite::encodeTagAndValue(cbor, ur::CborLite::Major::semantic, size_t(309)); 126 | ur::CborLite::encodeBytes(cbor, v); 127 | ur::UR ur("crypto-sskr", cbor); 128 | auto s = ur::UREncoder::encode(ur); 129 | strings.push_back(s); 130 | } 131 | auto all_strings = join(strings, "\n"); 132 | p->output = all_strings; 133 | } else { 134 | StringVector strings; 135 | for (int i = 0; i < share_count; i++) { 136 | uint8_t* bytes = shares_buffer + (i * bytes_in_each_share); 137 | auto v = ByteVector(bytes, bytes + bytes_in_each_share); 138 | ByteVector cbor; 139 | ur::CborLite::encodeTagAndValue(cbor, ur::CborLite::Major::semantic, size_t(309)); 140 | ur::CborLite::encodeBytes(cbor, v); 141 | auto s = ur::Bytewords::encode(ur::Bytewords::standard, cbor); 142 | strings.push_back(s); 143 | } 144 | auto all_strings = join(strings, "\n"); 145 | p->output = all_strings; 146 | } 147 | } 148 | 149 | FormatSSKR::FormatSSKR() 150 | : Format(Format::Key::sskr, "sskr"), 151 | groups({{1, 1}}) { 152 | groups_threshold = 1; 153 | } 154 | -------------------------------------------------------------------------------- /src/format-sskr.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format-sskr.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | 13 | #include "format.hpp" 14 | #include "utils.hpp" 15 | 16 | class FormatSSKR : public Format { 17 | public: 18 | FormatSSKR(); 19 | 20 | virtual void process_input(Params* p) override; 21 | virtual void process_output(Params* p) override; 22 | 23 | static bool is_seed_length_valid(size_t seed_len); 24 | 25 | size_t groups_threshold; 26 | std::vector groups; 27 | }; 28 | -------------------------------------------------------------------------------- /src/format.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // format.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "format.hpp" 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "utils.hpp" 15 | 16 | static const std::vector format_key_names = { 17 | "random", 18 | "hex", 19 | "bits", 20 | "cards", 21 | "dice", 22 | "base6", 23 | "base10", 24 | "ints", 25 | "bip39", 26 | "sskr", 27 | "btw", 28 | "btwu", 29 | "btwm" 30 | }; 31 | 32 | Format::Key Format::key_for_string(const std::string &arg) { 33 | for(auto i = 0; i < format_key_names.size(); i++) { 34 | if(arg == format_key_names[i]) { 35 | return (Format::Key)i; 36 | } 37 | } 38 | 39 | return Format::Key::unknown; 40 | } 41 | -------------------------------------------------------------------------------- /src/format.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // format.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | 12 | class Params; 13 | 14 | class Format { 15 | public: 16 | enum class Key { 17 | unknown = -1, 18 | random, 19 | hex, 20 | bits, 21 | cards, 22 | dice, 23 | base6, 24 | base10, 25 | ints, 26 | bip39, 27 | sskr, 28 | bytewords, 29 | bytewords_uri, 30 | bytewords_minimal 31 | }; 32 | 33 | Format(Key key, const std::string &name) : key(key), name(name) {} 34 | virtual ~Format() {} 35 | 36 | Key key; 37 | std::string name; 38 | 39 | virtual void process_input(Params *) = 0; 40 | virtual void process_output(Params *) = 0; 41 | 42 | static Key key_for_string(const std::string &arg); 43 | }; 44 | -------------------------------------------------------------------------------- /src/formats-all.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // formats-all.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include "format-base6.hpp" 11 | #include "format-base10.hpp" 12 | #include "format-bip39.hpp" 13 | #include "format-bits.hpp" 14 | #include "format-cards.hpp" 15 | #include "format-dice.hpp" 16 | #include "format-hex.hpp" 17 | #include "format-ints.hpp" 18 | #include "format-random.hpp" 19 | #include "format-sskr.hpp" 20 | #include "format-bytewords.hpp" 21 | #include "format-bytewords-uri.hpp" 22 | #include "format-bytewords-minimal.hpp" 23 | 24 | bool is_random(const Format* f) { return dynamic_cast(f) != NULL; } 25 | bool is_hex(const Format* f) { return dynamic_cast(f) != NULL; } 26 | bool is_bits(const Format* f) { return dynamic_cast(f) != NULL; } 27 | bool is_cards(const Format* f) { return dynamic_cast(f) != NULL; } 28 | bool is_dice(const Format* f) { return dynamic_cast(f) != NULL; } 29 | bool is_base6(const Format* f) { return dynamic_cast(f) != NULL; } 30 | bool is_base10(const Format* f) { return dynamic_cast(f) != NULL; } 31 | bool is_ints(const Format* f) { return dynamic_cast(f) != NULL; } 32 | bool is_bip39(const Format* f) { return dynamic_cast(f) != NULL; } 33 | bool is_sskr(const Format* f) { return dynamic_cast(f) != NULL; } 34 | bool is_bytewords(const Format* f) { return dynamic_cast(f) != NULL; } 35 | bool is_bytewords_uri(const Format* f) { return dynamic_cast(f) != NULL; } 36 | bool is_bytewords_minimal(const Format* f) { return dynamic_cast(f) != NULL; } 37 | bool is_bytewords_any(const Format* f) { return is_bytewords(f) || is_bytewords_uri(f) || is_bytewords_minimal(f); } 38 | -------------------------------------------------------------------------------- /src/hkdf.c: -------------------------------------------------------------------------------- 1 | // Permission is hereby granted, free of charge, to any person obtaining a copy 2 | // of this software and associated documentation files (the "Software"), to deal 3 | // in the Software without restriction, including without limitation the rights 4 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5 | // copies of the Software, and to permit persons to whom the Software is 6 | // furnished to do so, subject to the following conditions: 7 | 8 | // The above copyright notice and this permission notice shall be included in 9 | // all copies or substantial portions of the Software. 10 | 11 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17 | // THE SOFTWARE. 18 | 19 | #include "hkdf.h" 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | 26 | void hkdf_sha256(uint8_t *okm, size_t okm_size, 27 | const uint8_t *s, size_t ssize, 28 | const uint8_t *k, size_t ksize, 29 | const uint8_t *info, size_t isize) 30 | { 31 | uint8_t prk[SHA256_DIGEST_LENGTH]; 32 | uint8_t t[SHA256_DIGEST_LENGTH]; 33 | HMAC_SHA256_CTX ctx; 34 | unsigned char c; 35 | 36 | assert(okm_size < 255 * sizeof(t)); 37 | 38 | /* RFC 5869: 39 | * 40 | * 2.2. Step 1: Extract 41 | * 42 | * HKDF-Extract(salt, IKM) -> PRK 43 | * 44 | * Options: 45 | * Hash a hash function; HashLen denotes the length of the 46 | * hash function output in octets 47 | * 48 | * Inputs: 49 | * salt optional salt value (a non-secret random value); 50 | * if not provided, it is set to a string of HashLen zeros. 51 | * IKM input keying material 52 | * 53 | * Output: 54 | * PRK a pseudorandom key (of HashLen octets) 55 | * 56 | * The output PRK is calculated as follows: 57 | * 58 | * PRK = HMAC-Hash(salt, IKM) 59 | */ 60 | if(s == NULL || ssize == 0) { 61 | uint8_t a[SHA256_DIGEST_LENGTH]; 62 | memset(a, 0, SHA256_DIGEST_LENGTH); 63 | hmac_sha256(a, SHA256_DIGEST_LENGTH, k, ksize, prk); 64 | } else { 65 | hmac_sha256(s, ssize, k, ksize, prk); 66 | } 67 | 68 | /* 69 | * 2.3. Step 2: Expand 70 | * 71 | * HKDF-Expand(PRK, info, L) -> OKM 72 | * 73 | * Options: 74 | * Hash a hash function; HashLen denotes the length of the 75 | * hash function output in octets 76 | * 77 | * Inputs: 78 | * PRK a pseudorandom key of at least HashLen octets 79 | * (usually, the output from the extract step) 80 | * info optional context and application specific information 81 | * (can be a zero-length string) 82 | * L length of output keying material in octets 83 | * (<= 255*HashLen) 84 | * 85 | * Output: 86 | * OKM output keying material (of L octets) 87 | * 88 | * The output OKM is calculated as follows: 89 | * 90 | * N = ceil(L/HashLen) 91 | * T = T(1) | T(2) | T(3) | ... | T(N) 92 | * OKM = first L octets of T 93 | * 94 | * where: 95 | * T(0) = empty string (zero length) 96 | * T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) 97 | * T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) 98 | * T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) 99 | * ... 100 | * 101 | * (where the constant concatenated to the end of each T(n) is a 102 | * single octet.) 103 | */ 104 | c = 1; 105 | hmac_sha256_Init(&ctx, prk, sizeof(prk)); 106 | hmac_sha256_Update(&ctx, info, isize); 107 | hmac_sha256_Update(&ctx, &c, 1); 108 | hmac_sha256_Final(&ctx, t); 109 | 110 | while (okm_size > sizeof(t)) { 111 | memcpy(okm, &t, sizeof(t)); 112 | okm = okm + sizeof(t); 113 | okm_size -= sizeof(t); 114 | 115 | c++; 116 | hmac_sha256_Init(&ctx, prk, sizeof(prk)); 117 | hmac_sha256_Update(&ctx, t, sizeof(t)); 118 | hmac_sha256_Update(&ctx, info, isize); 119 | hmac_sha256_Update(&ctx, &c, 1); 120 | hmac_sha256_Final(&ctx, t); 121 | } 122 | memcpy(okm, &t, okm_size); 123 | } -------------------------------------------------------------------------------- /src/hkdf.h: -------------------------------------------------------------------------------- 1 | #ifndef CCAN_CRYPTO_HKDF_SHA256_H 2 | #define CCAN_CRYPTO_HKDF_SHA256_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | #include 27 | #include 28 | 29 | /** 30 | * hkdf_sha256 - generate a derived key 31 | * @okm: where to output the key 32 | * @okm_size: the number of bytes pointed to by @okm (must be less than 255*32) 33 | * @s: salt 34 | * @ssize: the number of bytes pointed to by @s 35 | * @k: pointer to input key 36 | * @ksize: the number of bytes pointed to by @k 37 | * @info: pointer to info 38 | * @isize: the number of bytes pointed to by @info 39 | */ 40 | void hkdf_sha256(uint8_t *okm, size_t okm_size, 41 | const uint8_t *s, size_t ssize, 42 | const uint8_t *k, size_t ksize, 43 | const uint8_t *info, size_t isize); 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif /* CCAN_CRYPTO_HKDF_SHA256_H */ 50 | -------------------------------------------------------------------------------- /src/params.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // params.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "random.hpp" 19 | #include "utils.hpp" 20 | 21 | #define MAX_GROUPS 16 22 | #define MAX_RAW_GROUPS (MAX_GROUPS + 1) 23 | 24 | #define MAX_ARGS 256 25 | 26 | class RawParams { 27 | public: 28 | RawParams() { } 29 | 30 | std::string input_format; 31 | std::string output_format; 32 | std::string count; 33 | 34 | std::string ints_low; 35 | std::string ints_high; 36 | 37 | std::string random_deterministic; 38 | bool is_ur = false; 39 | std::string max_fragment_length; 40 | std::string fountain_parts; 41 | 42 | std::string sskr_groups_threshold; 43 | StringVector sskr_groups; 44 | 45 | StringVector args; 46 | }; 47 | 48 | class Format; 49 | 50 | class Params { 51 | public: 52 | Params() { } 53 | ~Params(); 54 | 55 | Format* input_format = NULL; 56 | Format* output_format = NULL; 57 | 58 | bool is_ur_out = false; 59 | bool is_ur_in = false; 60 | std::vector ur_shares; 61 | size_t max_fragment_length = 0; 62 | std::optional fountain_parts; 63 | 64 | StringVector shares; 65 | 66 | StringVector input; 67 | std::string output; 68 | 69 | ByteVector seed; 70 | 71 | size_t count = 0; 72 | 73 | char* deterministic_seed = NULL; 74 | random_generator rng = NULL; 75 | 76 | void validate(); 77 | 78 | RawParams raw; 79 | 80 | struct argp_state* state = nullptr; 81 | 82 | static Params* parse( int argc, char *argv[] ); 83 | void read_args_from_stdin(); 84 | 85 | std::string get_one_argument(); 86 | std::string get_combined_arguments(); 87 | StringVector get_multiple_arguments(); 88 | 89 | void set_ur_output(const ByteVector& cbor, const std::string& type); 90 | 91 | private: 92 | sskr_group_descriptor parse_group_spec(const std::string &string); 93 | 94 | void validate_count(); 95 | void validate_deterministic(); 96 | void validate_input_format(); 97 | void validate_count_for_input_format(); 98 | void validate_output_format(); 99 | void validate_output_for_input(); 100 | void validate_ints_specific(); 101 | void validate_bip39_specific(); 102 | void validate_sskr_specific(); 103 | void validate_input(); 104 | void validate_ur(); 105 | }; 106 | -------------------------------------------------------------------------------- /src/random.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // random.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include "random.hpp" 16 | #include "randombytes.h" 17 | #include "hkdf.h" 18 | 19 | using namespace std; 20 | 21 | void crypto_random(uint8_t* buf, size_t n, void* ctx) { 22 | assert(randombytes(buf, n) == 0); 23 | } 24 | 25 | static uint8_t deterministic_seed[SHA256_DIGEST_LENGTH]; 26 | static uint64_t deterministic_salt = 0; 27 | 28 | void seed_deterministic_string(const string &string) { 29 | sha256_Raw((uint8_t*)string.c_str(), string.length(), deterministic_seed); 30 | deterministic_salt = 0; 31 | } 32 | 33 | void deterministic_random(uint8_t* buf, size_t n, void* ctx) { 34 | deterministic_salt += 1; 35 | 36 | hkdf_sha256(buf, n, 37 | (uint8_t*)&deterministic_salt, sizeof(deterministic_salt), 38 | deterministic_seed, SHA256_DIGEST_LENGTH, 39 | NULL, 0); 40 | } 41 | 42 | ByteVector deterministic_random(const ByteVector &entropy, size_t n) { 43 | ByteVector result; 44 | result.resize(n); 45 | 46 | auto seed = sha256(entropy); 47 | 48 | hkdf_sha256(result.data(), n, 49 | NULL, 0, // no salt 50 | seed.data(), SHA256_DIGEST_LENGTH, 51 | NULL, 0); // no info 52 | 53 | return result; 54 | } 55 | 56 | ByteVector sha256_deterministic_random(const ByteVector &entropy, size_t n) { 57 | auto seed = sha256(entropy); 58 | if(n <= seed.size()) { 59 | return take(seed, n); 60 | } else { 61 | throw runtime_error("Random number generator limits reached."); 62 | } 63 | } 64 | 65 | ByteVector sha256_deterministic_random(const string &string, size_t n) { 66 | ByteVector entropy; 67 | std::copy(string.begin(), string.end(), back_inserter(entropy)); 68 | return sha256_deterministic_random(entropy, n); 69 | } 70 | -------------------------------------------------------------------------------- /src/random.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // random.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "utils.hpp" 15 | 16 | typedef void (*random_generator)(uint8_t*, size_t, void*); 17 | 18 | // Generates a buffer of random bytes using the OS's cryptographically strong random number generator. 19 | void crypto_random(uint8_t* buf, size_t n, void* ctx); 20 | 21 | // Seeds the cryptographically strong deterministic random number generator with the SHA256 digest of the string. 22 | void seed_deterministic_string(const std::string &string); 23 | 24 | // Generates a buffer of random bytes using the cryptographically strong deterministic random number generator. 25 | void deterministic_random(uint8_t* buf, size_t n, void* ctx); 26 | 27 | ByteVector deterministic_random(const ByteVector &entropy, size_t n); 28 | 29 | ByteVector sha256_deterministic_random(const ByteVector &entropy, size_t n); 30 | ByteVector sha256_deterministic_random(const std::string &string, size_t n); 31 | -------------------------------------------------------------------------------- /src/randombytes.c: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2017 Daan Sprenkels 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | // In the case that are compiling on linux, we need to define _GNU_SOURCE 24 | // *before* randombytes.h is included. Otherwise SYS_getrandom will not be 25 | // declared. 26 | #if defined(__linux__) 27 | # define _GNU_SOURCE 28 | #endif /* defined(__linux__) */ 29 | 30 | #include "randombytes.h" 31 | 32 | #if defined(_WIN32) 33 | /* Windows */ 34 | # include 35 | # include /* CryptAcquireContext, CryptGenRandom */ 36 | #endif /* defined(_WIN32) */ 37 | 38 | 39 | #if defined(__linux__) 40 | /* Linux */ 41 | // We would need to include , but not every target has access 42 | // to the linux headers. We only need RNDGETENTCNT, so we instead inline it. 43 | // RNDGETENTCNT is originally defined in `include/uapi/linux/random.h` in the 44 | // linux repo. 45 | # define RNDGETENTCNT 0x80045200 46 | 47 | # include 48 | # include 49 | # include 50 | # include 51 | # include 52 | # include 53 | # include 54 | # include 55 | # include 56 | # include 57 | # include 58 | 59 | // We need SSIZE_MAX as the maximum read len from /dev/urandom 60 | # if !defined(SSIZE_MAX) 61 | # define SSIZE_MAX (SIZE_MAX / 2 - 1) 62 | # endif /* defined(SSIZE_MAX) */ 63 | 64 | #endif /* defined(__linux__) */ 65 | 66 | 67 | #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) 68 | /* Dragonfly, FreeBSD, NetBSD, OpenBSD (has arc4random) */ 69 | # include 70 | # if defined(BSD) 71 | # include 72 | # endif 73 | #endif 74 | 75 | #if defined(__EMSCRIPTEN__) 76 | # include 77 | # include 78 | # include 79 | # include 80 | #endif /* defined(__EMSCRIPTEN__) */ 81 | 82 | 83 | #if defined(_WIN32) 84 | static int randombytes_win32_randombytes(void* buf, const size_t n) 85 | { 86 | HCRYPTPROV ctx; 87 | BOOL tmp; 88 | 89 | tmp = CryptAcquireContext(&ctx, NULL, NULL, PROV_RSA_FULL, 90 | CRYPT_VERIFYCONTEXT); 91 | if (tmp == FALSE) return -1; 92 | 93 | tmp = CryptGenRandom(ctx, n, (BYTE*) buf); 94 | if (tmp == FALSE) return -1; 95 | 96 | tmp = CryptReleaseContext(ctx, 0); 97 | if (tmp == FALSE) return -1; 98 | 99 | return 0; 100 | } 101 | #endif /* defined(_WIN32) */ 102 | 103 | 104 | #if defined(__linux__) && defined(SYS_getrandom) 105 | static int randombytes_linux_randombytes_getrandom(void *buf, size_t n) 106 | { 107 | /* I have thought about using a separate PRF, seeded by getrandom, but 108 | * it turns out that the performance of getrandom is good enough 109 | * (250 MB/s on my laptop). 110 | */ 111 | size_t offset = 0, chunk; 112 | int ret; 113 | while (n > 0) { 114 | /* getrandom does not allow chunks larger than 33554431 */ 115 | chunk = n <= 33554431 ? n : 33554431; 116 | do { 117 | ret = syscall(SYS_getrandom, (char *)buf + offset, chunk, 0); 118 | } while (ret == -1 && errno == EINTR); 119 | if (ret < 0) return ret; 120 | offset += ret; 121 | n -= ret; 122 | } 123 | assert(n == 0); 124 | return 0; 125 | } 126 | #endif /* defined(__linux__) && defined(SYS_getrandom) */ 127 | 128 | 129 | #if defined(__linux__) && !defined(SYS_getrandom) 130 | static int randombytes_linux_read_entropy_ioctl(int device, int *entropy) 131 | { 132 | return ioctl(device, RNDGETENTCNT, entropy); 133 | } 134 | 135 | static int randombytes_linux_read_entropy_proc(FILE *stream, int *entropy) 136 | { 137 | int retcode; 138 | do { 139 | rewind(stream); 140 | retcode = fscanf(stream, "%d", entropy); 141 | } while (retcode != 1 && errno == EINTR); 142 | if (retcode != 1) { 143 | return -1; 144 | } 145 | return 0; 146 | } 147 | 148 | static int randombytes_linux_wait_for_entropy(int device) 149 | { 150 | /* We will block on /dev/random, because any increase in the OS' entropy 151 | * level will unblock the request. I use poll here (as does libsodium), 152 | * because we don't *actually* want to read from the device. */ 153 | enum { IOCTL, PROC } strategy = IOCTL; 154 | const int bits = 128; 155 | struct pollfd pfd; 156 | int fd; 157 | FILE *proc_file; 158 | int retcode, retcode_error = 0; // Used as return codes throughout this function 159 | int entropy = 0; 160 | 161 | /* If the device has enough entropy already, we will want to return early */ 162 | retcode = randombytes_linux_read_entropy_ioctl(device, &entropy); 163 | // printf("errno: %d (%s)\n", errno, strerror(errno)); 164 | if (retcode != 0 && (errno == ENOTTY || errno == ENOSYS)) { 165 | // The ioctl call on /dev/urandom has failed due to a 166 | // - ENOTTY (unsupported action), or 167 | // - ENOSYS (invalid ioctl; this happens on MIPS, see #22). 168 | // 169 | // We will fall back to reading from 170 | // `/proc/sys/kernel/random/entropy_avail`. This less ideal, 171 | // because it allocates a file descriptor, and it may not work 172 | // in a chroot. But at this point it seems we have no better 173 | // options left. 174 | strategy = PROC; 175 | // Open the entropy count file 176 | proc_file = fopen("/proc/sys/kernel/random/entropy_avail", "r"); 177 | } else if (retcode != 0) { 178 | // Unrecoverable ioctl error 179 | return -1; 180 | } 181 | if (entropy >= bits) { 182 | return 0; 183 | } 184 | 185 | do { 186 | fd = open("/dev/random", O_RDONLY); 187 | } while (fd == -1 && errno == EINTR); /* EAGAIN will not occur */ 188 | if (fd == -1) { 189 | /* Unrecoverable IO error */ 190 | return -1; 191 | } 192 | 193 | pfd.fd = fd; 194 | pfd.events = POLLIN; 195 | for (;;) { 196 | retcode = poll(&pfd, 1, -1); 197 | if (retcode == -1 && (errno == EINTR || errno == EAGAIN)) { 198 | continue; 199 | } else if (retcode == 1) { 200 | if (strategy == IOCTL) { 201 | retcode = randombytes_linux_read_entropy_ioctl(device, &entropy); 202 | } else if (strategy == PROC) { 203 | retcode = randombytes_linux_read_entropy_proc(proc_file, &entropy); 204 | } else { 205 | return -1; // Unreachable 206 | } 207 | 208 | if (retcode != 0) { 209 | // Unrecoverable I/O error 210 | retcode_error = retcode; 211 | break; 212 | } 213 | if (entropy >= bits) { 214 | break; 215 | } 216 | } else { 217 | // Unreachable: poll() should only return -1 or 1 218 | retcode_error = -1; 219 | break; 220 | } 221 | } 222 | do { 223 | retcode = close(fd); 224 | } while (retcode == -1 && errno == EINTR); 225 | if (strategy == PROC) { 226 | do { 227 | retcode = fclose(proc_file); 228 | } while (retcode == -1 && errno == EINTR); 229 | } 230 | if (retcode_error != 0) { 231 | return retcode_error; 232 | } 233 | return retcode; 234 | } 235 | 236 | 237 | static int randombytes_linux_randombytes_urandom(void *buf, size_t n) 238 | { 239 | int fd; 240 | size_t offset = 0; 241 | do { 242 | fd = open("/dev/urandom", O_RDONLY); 243 | } while (fd == -1 && errno == EINTR); 244 | if (fd == -1) return -1; 245 | if (randombytes_linux_wait_for_entropy(fd) == -1) return -1; 246 | 247 | while (n > 0) { 248 | size_t count = n <= SSIZE_MAX ? n : SSIZE_MAX; 249 | ssize_t tmp = read(fd, (char *)buf + offset, count); 250 | if (tmp == -1 && (errno == EAGAIN || errno == EINTR)) { 251 | continue; 252 | } 253 | if (tmp == -1) return -1; /* Unrecoverable IO error */ 254 | offset += tmp; 255 | n -= tmp; 256 | } 257 | assert(n == 0); 258 | return 0; 259 | } 260 | #endif /* defined(__linux__) && !defined(SYS_getrandom) */ 261 | 262 | 263 | #if defined(BSD) 264 | static int randombytes_bsd_randombytes(void *buf, size_t n) 265 | { 266 | arc4random_buf(buf, n); 267 | return 0; 268 | } 269 | #endif /* defined(BSD) */ 270 | 271 | 272 | #if defined(__EMSCRIPTEN__) 273 | static int randombytes_js_randombytes_nodejs(void *buf, size_t n) { 274 | const int ret = EM_ASM_INT({ 275 | var crypto; 276 | try { 277 | crypto = require('crypto'); 278 | } catch (error) { 279 | return -2; 280 | } 281 | try { 282 | writeArrayToMemory(crypto.randomBytes($1), $0); 283 | return 0; 284 | } catch (error) { 285 | return -1; 286 | } 287 | }, buf, n); 288 | switch (ret) { 289 | case 0: 290 | return 0; 291 | case -1: 292 | errno = EINVAL; 293 | return -1; 294 | case -2: 295 | errno = ENOSYS; 296 | return -1; 297 | } 298 | assert(false); // Unreachable 299 | } 300 | #endif /* defined(__EMSCRIPTEN__) */ 301 | 302 | 303 | int randombytes(void *buf, size_t n) 304 | { 305 | #if defined(__EMSCRIPTEN__) 306 | //# pragma message("Using crypto api from NodeJS") 307 | return randombytes_js_randombytes_nodejs(buf, n); 308 | #elif defined(__linux__) 309 | # if defined(SYS_getrandom) 310 | //# pragma message("Using getrandom system call") 311 | /* Use getrandom system call */ 312 | return randombytes_linux_randombytes_getrandom(buf, n); 313 | # else 314 | //# pragma message("Using /dev/urandom device") 315 | /* When we have enough entropy, we can read from /dev/urandom */ 316 | return randombytes_linux_randombytes_urandom(buf, n); 317 | # endif 318 | #elif defined(BSD) 319 | //# pragma message("Using arc4random system call") 320 | /* Use arc4random system call */ 321 | return randombytes_bsd_randombytes(buf, n); 322 | #elif defined(_WIN32) 323 | //# pragma message("Using Windows cryptographic API") 324 | /* Use windows API */ 325 | return randombytes_win32_randombytes(buf, n); 326 | #else 327 | # error "randombytes(...) is not supported on this platform" 328 | #endif 329 | } 330 | -------------------------------------------------------------------------------- /src/randombytes.h: -------------------------------------------------------------------------------- 1 | // The MIT License 2 | // 3 | // Copyright (c) 2017 Daan Sprenkels 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #ifndef sss_RANDOMBYTES_H 24 | #define sss_RANDOMBYTES_H 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | #ifdef _WIN32 31 | /* Load size_t on windows */ 32 | #include 33 | #else 34 | #include 35 | #endif /* _WIN32 */ 36 | 37 | 38 | /* 39 | * Write `n` bytes of high quality random bytes to `buf` 40 | */ 41 | int randombytes(void *buf, size_t n); 42 | 43 | #ifdef __cplusplus 44 | } 45 | #endif 46 | 47 | #endif /* sss_RANDOMBYTES_H */ 48 | -------------------------------------------------------------------------------- /src/seedtool.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // seedtool.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include 9 | #include 10 | 11 | #include "params.hpp" 12 | #include "format.hpp" 13 | 14 | using namespace std; 15 | 16 | int main( int argc, char *argv[] ) { 17 | auto p = Params::parse(argc, argv); 18 | 19 | try { 20 | p->input_format->process_input(p); 21 | p->output_format->process_output(p); 22 | 23 | if(p->output.empty()) { 24 | throw runtime_error("An internal error occurred."); 25 | } 26 | 27 | cout << p->output << endl; 28 | 29 | } catch(exception &e) { 30 | cerr << argv[0] << ": " << e.what() << endl; 31 | exit(1); 32 | } 33 | 34 | delete p; 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /src/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Echo any provided arguments. 4 | # [ $# -gt 0 ] && echo "#:$# 1:$1 2:$2 3:$3" 5 | 6 | SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" 7 | SEEDTOOL="${1:-${SCRIPT_DIR}/seedtool} --deterministic TEST" 8 | SHUNIT2="${SCRIPT_DIR}/../deps/shunit2/shunit2" 9 | 10 | testDefault() 11 | { 12 | assertEquals $'9d347f841a4e2ce6bc886e1aee74d824' \ 13 | "$(${SEEDTOOL})" 14 | } 15 | 16 | testRedundantDefault() 17 | { 18 | assertEquals $'9d347f841a4e2ce6bc886e1aee74d824' \ 19 | "$(${SEEDTOOL} --in random --out hex)" 20 | } 21 | 22 | testOutBTW() 23 | { 24 | assertEquals $'next edge lamb liar city girl draw visa roof logo jolt city waxy jury trip dark loud duty obey monk' \ 25 | "$(${SEEDTOOL} --out btw)" 26 | } 27 | 28 | testInBTW() 29 | { 30 | assertEquals $'9d347f841a4e2ce6bc886e1aee74d824' \ 31 | "$(${SEEDTOOL} --in btw 'next edge lamb liar city girl draw visa roof logo jolt city waxy jury trip dark loud duty obey monk')" 32 | } 33 | 34 | testOutBTWU() 35 | { 36 | assertEquals $'deli-need-cats-taxi-dice-door-webs-vows-free-zero-legs-wall-half-waxy-trip-oval-memo-sets-rock-hill' \ 37 | "$(${SEEDTOOL} --in hex --out btwu 279b18d0282aefe845fb83e956eed8a6)" 38 | } 39 | 40 | testOutBTWM() 41 | { 42 | assertEquals $'dindcstidedrwsvsfezolswlhfwytpolmossrkhl' \ 43 | "$(${SEEDTOOL} --in hex --out btwm 279b18d0282aefe845fb83e956eed8a6)" 44 | } 45 | 46 | testOutBits() 47 | { 48 | assertEquals $'1001000111001010' \ 49 | "$(${SEEDTOOL} --out bits)" 50 | } 51 | 52 | testOutCards() 53 | { 54 | assertEquals $'6hjckdah6c4dtc8skh2htd6ctsjd5s8c' \ 55 | "$(${SEEDTOOL} --out cards)" 56 | } 57 | 58 | testOutDice() 59 | { 60 | assertEquals $'4234232654326352' \ 61 | "$(${SEEDTOOL} --out dice)" 62 | } 63 | 64 | testOutBase6() 65 | { 66 | assertEquals $'3123121543215241' \ 67 | "$(${SEEDTOOL} --out base6)" 68 | } 69 | 70 | testOutBase10() 71 | { 72 | assertEquals $'6245132875418481' \ 73 | "$(${SEEDTOOL} --out base10)" 74 | } 75 | 76 | testOut5Cards() 77 | { 78 | assertEquals $'6hjckdah6c' \ 79 | "$(${SEEDTOOL} --out cards --count 5)" 80 | } 81 | 82 | testOutInts() 83 | { 84 | assertEquals $'6 2 4 5 1 3 2 8 7 5 4 1 8 4 8 1' \ 85 | "$(${SEEDTOOL} --out ints)" 86 | } 87 | 88 | testOutIntsRange() 89 | { 90 | assertEquals $'62 21 50 52 11 31 18 90' \ 91 | "$(${SEEDTOOL} --out ints --count 8 --low 1 --high 100)" 92 | } 93 | 94 | testOutBIP39() 95 | { 96 | assertEquals $'outdoor physical three cruel tissue infant vendor assist brain inhale current emotion' \ 97 | "$(${SEEDTOOL} --out bip39)" 98 | } 99 | 100 | testOutBIP39Count32() 101 | { 102 | assertEquals $'outdoor physical three cruel tissue infant vendor assist brain inhale current embrace clinic knife mystery metal horror item twice assault wedding marble song buyer' \ 103 | "$(${SEEDTOOL} --out bip39 --count 32)" 104 | } 105 | 106 | testOutSSKR() 107 | { 108 | assertEquals $'tuna acid epic gyro many meow able able able next edge lamb liar city girl draw visa roof logo jolt city waxy jury trip dark safe arch flew what' \ 109 | "$(${SEEDTOOL} --out sskr)" 110 | } 111 | 112 | testOutSSKRCount32() 113 | { 114 | assertEquals $'tuna acid epic hard data many meow able able able next edge lamb liar city girl draw visa roof logo jolt city waxy jury trip dark flew purr yell idle news horn join pool ugly poem atom task many bias junk soap yoga idea yell work' \ 115 | "$(${SEEDTOOL} --out sskr --count 32)" 116 | } 117 | 118 | testOutSSKRGroup2Of3() 119 | { 120 | assertEquals $'tuna acid epic gyro many meow able acid able mild fern pool door purr calm trip cyan flew zest cats tuna omit figs bias acid aunt keys play frog 121 | tuna acid epic gyro many meow able acid acid keep undo peck poem kiwi jazz cola luck hope rock into film jolt lava flux rust gala sets ruin toil 122 | tuna acid epic gyro many meow able acid also girl void oval fish exam veto gala inky keys jump visa barn cusp high miss monk jazz numb dice foxy' \ 123 | "$(${SEEDTOOL} --out sskr --group 2-of-3)" 124 | } 125 | 126 | testOutSSKR3Groups() 127 | { 128 | assertEquals $'tuna acid epic gyro many meow brag acid able noon diet race hope glow junk kept oval jump hope heat keys high barn hang into next miss logo oval 129 | tuna acid epic gyro many meow brag acid acid heat noon peck aqua keno wolf wasp fund aqua gush cyan gear hill inky drop scar buzz city toys mild 130 | tuna acid epic gyro many meow brag acid also belt high luau wall figs iris heat huts noon gala paid cook holy trip omit edge miss cats keep runs 131 | tuna acid epic gyro many meow brag brag able kiwi pool yell user math girl figs gift free part when liar kiln view iced buzz keep eyes taxi wolf 132 | tuna acid epic gyro many meow brag brag acid surf miss barn kick surf miss lamb calm miss dark song kite fuel real hill mint apex dull runs unit 133 | tuna acid epic gyro many meow brag brag also skew love quad dull iced join each curl numb data aqua wand vows owls idea cash keep echo keys math 134 | tuna acid epic gyro many meow brag brag apex kept quad fund loud film quiz junk kiln jump paid fish brag toil yank high meow apex data cash ruin 135 | tuna acid epic gyro many meow brag brag aqua epic open wave main high calm echo taxi void paid fact kiln soap tiny list join kiln rust blue flap 136 | tuna acid epic gyro many meow brag cusp able legs acid keep menu film yell very lava undo flew curl wolf soap chef idle fuel king runs trip urge 137 | tuna acid epic gyro many meow brag cusp acid puff kiwi crux soap rock toys bulb hill jade beta jade zinc loud void junk kiln soap draw edge pose 138 | tuna acid epic gyro many meow brag cusp also heat apex plus mild glow saga lava yoga user game diet mild gyro limp puma down echo quiz user oboe 139 | tuna acid epic gyro many meow brag cusp apex iron lamb yurt taco song veto keep data iris atom idea need bulb king oval calm lava deli echo time 140 | tuna acid epic gyro many meow brag cusp aqua vast rust bald iron fuel grim gyro eyes chef dark kept surf mild swan bulb slot draw kick zero onyx' \ 141 | "$(${SEEDTOOL} --out sskr --group-threshold 2 --group 2-of-3 --group 3-of-5 --group 3-of-5)" 142 | } 143 | 144 | testInBits() 145 | { 146 | assertEquals $'8d933e43b1bc8f2e3fc27adc98ad4534' \ 147 | "$(${SEEDTOOL} --in bits 1110110001110111)" 148 | } 149 | 150 | testInCards() 151 | { 152 | assertEquals $'7df301924511326d7350be14c9e7176d' \ 153 | "$(${SEEDTOOL} --in cards 6c9s8c7c9c4cah6c2sjs7d5c2s4c4dqs)" 154 | } 155 | 156 | testInCardsCount32() 157 | { 158 | assertEquals $'7df301924511326d7350be14c9e7176d98e945f9ad0ed034726ad4ee0de59c25' \ 159 | "$(${SEEDTOOL} --count 32 --in cards 6c9s8c7c9c4cah6c2sjs7d5c2s4c4dqs)" 160 | } 161 | 162 | testInDice() 163 | { 164 | assertEquals $'77ae0de807d60367311eb040c70690d2' \ 165 | "$(${SEEDTOOL} --in dice 3343462611234633)" 166 | } 167 | 168 | testInBase6() 169 | { 170 | assertEquals $'51621269b3a91fe6482ceb7779f0d1d1' \ 171 | "$(${SEEDTOOL} --in base6 3242235101442242)" 172 | } 173 | 174 | testInBase10() 175 | { 176 | assertEquals $'a0ca21e20db54b4df7479737c145f6db' \ 177 | "$(${SEEDTOOL} --in base10 3190125)" 178 | } 179 | 180 | testInInts() 181 | { 182 | assertEquals $'a38385ba7a67b7f5882b37f75b43c2df' \ 183 | "$(${SEEDTOOL} --in ints 71 22 95 6 23 65 27 10 67 16)" 184 | } 185 | 186 | testDicePipe() 187 | { 188 | assertEquals $'eefa19b88c5846e71fcb52d007066ae4a2bd0be166e12c8de95c8e71a712c581' \ 189 | "$(${SEEDTOOL} --out dice | ${SEEDTOOL} --in dice --count 32)" 190 | } 191 | 192 | testInBIP39OutBTW() 193 | { 194 | assertEquals $'love exam mint dark bias item mint atom open kept soap list whiz view soap fact jugs obey idle jugs' \ 195 | "$(${SEEDTOOL} --in bip39 --out btw mechanic royal math burst practice addict noise weekend margin now improve invest)" 196 | } 197 | 198 | testInSSKR() 199 | { 200 | assertEquals $'82f188b091c38fced97bb45732bddf7e' \ 201 | "$(${SEEDTOOL} --in sskr 'tuna acid epic gyro edge next able able able leaf when logo puff maze scar many taco tuna king quiz hang easy ruby user knob omit time chef slot')" 202 | } 203 | 204 | testInSSKR2Of3() 205 | { 206 | assertEquals $'2c4b163bfe9b791dbc0e755b911d01f6' \ 207 | "$(${SEEDTOOL} --in sskr \ 208 | 'tuna acid epic gyro edge next able acid able flux down eyes pool task cyan gyro kept exit paid wave high news bias zone zaps calm note poem aqua' \ 209 | 'tuna acid epic gyro edge next able acid also wolf vows bald sets claw bald dull cost slot inky liar work note tied zest safe crux kiln work exit')" 210 | } 211 | 212 | testOutUR() 213 | { 214 | # seedtool --deterministic TEST --ur 215 | assertEquals $'ur:seed/oyadgdnteelblrcygldwvarflojtcywyjytpdkjspafltb' \ 216 | "$(${SEEDTOOL} --ur)" 217 | } 218 | 219 | testInUR() 220 | { 221 | assertEquals $'9d347f841a4e2ce6bc886e1aee74d824' \ 222 | "$(${SEEDTOOL} --in ur ur:seed/oyadgdnteelblrcygldwvarflojtcywyjytpdkjspafltb)" 223 | } 224 | 225 | testOutMultipartUR() 226 | { 227 | assertEquals $'ur:seed/1-5/lpadahcfadmdcyknoxqdgohdgyoyadhkadmhnteelblrcygldwvarflojtcywyjytpdkfwprylienshnjnpluypmamtkmybsjkspvseesawmrltdlnlgkplfbkqzzoglfeoyaegsnedtrowsdpgtimmwzspfqdjkhshyfrylenpdnnnswmbeheclaszoyknbvavs 228 | ur:seed/2-5/lpaoahcfadmdcyknoxqdgohdgygmdstpoennbtflwykbtpktgwcxdkhtskwkkgmdmdlubblstnoxpkpysotntbcmotbdwfetqzwsckmscadwssgarysfeomohdytfhlbmeottiiogmdnayhholprylstdieytohtweknvtwsdifhbwsptadlzsldrpnsdeesecrd 229 | ur:seed/3-5/lpaxahcfadmdcyknoxqdgohdgypscsutkkiyfzeyvtyajlvlsewnhkjltduohddwinbschfzkiaygmmudpcnkklahfoxdksgsgvlrstyvlbsvsaxbsmwenfezturgtlnuecwfehgatkspriymotofgcemhguskgeflfyfspliorntefgdkykpswzwyrydwlamdft 230 | ur:seed/4-5/lpaaahcfadmdcyknoxqdgohdgywtpfvwdeecahtdhhvalrnynbtiwnbdctuesabtmnecvapratdwlbvltpgsglmdbnmknebkkscymofpkteyvoatjlqdaovesffhylgdimamcyadctgstymddlynpefppfemlkntknghveglrypslaahtblyvdspolptcpaxrpgs 231 | ur:seed/5-5/lpahahcfadmdcyknoxqdgohdgypkflsfmdfxjydpioihltbnwppfhtielguthtwdpdihaykgoyclentldykkmnvedsbwuyeojejennbkrtkevotacppyjsvdgohtvewenyneylfekihgcplpgljoisgwverkmokgldyavseojehncfvakgehcmrojlwezmdnkkwe' \ 232 | "$(${SEEDTOOL} --count 400 --ur=100)" 233 | } 234 | 235 | testInMultipartUR() 236 | { 237 | assertEquals $'9d347f841a4e2ce6bc886e1aee74d82442b2f7649c606daedbad06cf8f0f73c8e834c2ebb7d2868d75820ab4fb4e45a1004c9f29b8ef2d4d6a94fab0b373615e3bf736a89e9ceb105f2109fb5226d8a29e0d47ee7ed8774f20245ac5f47b95958b1483daa4aaabc9dad616a30bf338b4ef1e971d2cc449bdcc339258f93f7f91a3d067522b085ca6b2f7c72732ce5aed7ae0ef273f13c8d92ffa89b69cac18dd79664032e0f86fe3c1f1596fd2dc582c690f17407d0852932d23798056a424cacae3bfd4e30fe8030f943645fcdf4d86de1b45570778b26692ce461c9053c54a47443dae67bed34624f5acf2eebdf0b0e5283505d25ce6849aa0d0f10b1fdec20d8e35e6b2072c7fe3d84c4e950c989f0a781a92417732e2076fb302e4cc3ff7506a061a011f4cd4952ff6af41b0378c9d7a54e44ebdac8005d681e7c8a6a9aa47cc9543742d6765870cecb05a648ddd5aeaa865087ba12136d530798ee42613db336b6b9e0ac07ce2d922ab71e7555ae4ed9a9ff7457d5722854e70684fe4bb927b89f8e8336b6019e67b3116b86fed' \ 238 | "$(${SEEDTOOL} --in ur 'ur:seed/1-5/lpadahcfadmdcyknoxqdgohdgyoyadhkadmhnteelblrcygldwvarflojtcywyjytpdkfwprylienshnjnpluypmamtkmybsjkspvseesawmrltdlnlgkplfbkqzzoglfeoyaegsnedtrowsdpgtimmwzspfqdjkhshyfrylenpdnnnswmbeheclaszoyknbvavs' \ 239 | 'ur:seed/2-5/lpaoahcfadmdcyknoxqdgohdgygmdstpoennbtflwykbtpktgwcxdkhtskwkkgmdmdlubblstnoxpkpysotntbcmotbdwfetqzwsckmscadwssgarysfeomohdytfhlbmeottiiogmdnayhholprylstdieytohtweknvtwsdifhbwsptadlzsldrpnsdeesecrd' \ 240 | 'ur:seed/3-5/lpaxahcfadmdcyknoxqdgohdgypscsutkkiyfzeyvtyajlvlsewnhkjltduohddwinbschfzkiaygmmudpcnkklahfoxdksgsgvlrstyvlbsvsaxbsmwenfezturgtlnuecwfehgatkspriymotofgcemhguskgeflfyfspliorntefgdkykpswzwyrydwlamdft' \ 241 | 'ur:seed/4-5/lpaaahcfadmdcyknoxqdgohdgywtpfvwdeecahtdhhvalrnynbtiwnbdctuesabtmnecvapratdwlbvltpgsglmdbnmknebkkscymofpkteyvoatjlqdaovesffhylgdimamcyadctgstymddlynpefppfemlkntknghveglrypslaahtblyvdspolptcpaxrpgs' \ 242 | 'ur:seed/5-5/lpahahcfadmdcyknoxqdgohdgypkflsfmdfxjydpioihltbnwppfhtielguthtwdpdihaykgoyclentldykkmnvedsbwuyeojejennbkrtkevotacppyjsvdgohtvewenyneylfekihgcplpgljoisgwverkmokgldyavseojehncfvakgehcmrojlwezmdnkkwe')" 243 | } 244 | 245 | testOutFountainUR() 246 | { 247 | assertEquals $'ur:seed/1-7/lpadatcfadehcyetoyioluhddwoyadhkaddwnteelblrcygldwvarflojtcywyjytpdkfwprylienshnjnpluypmamtkmybsjkspvseesawmrltdlnbkaatllr 248 | ur:seed/2-7/lpaoatcfadehcyetoyioluhddwlgkplfbkqzzoglfeoyaegsnedtrowsdpgtimmwzspfqdjkhshyfrylenpdnnnswmbeheclaszogmdstpoennbtfljpyaihsn 249 | ur:seed/3-7/lpaxatcfadehcyetoyioluhddwwykbtpktgwcxdkhtskwkkgmdmdlubblstnoxpkpysotntbcmotbdwfetqzwsckmscadwssgarysfeomohdytfhlblerhdest 250 | ur:seed/4-7/lpaaatcfadehcyetoyioluhddwmeottiiogmdnayhholprylstdieytohtweknvtwsdifhbwsptadlzsldrpnspscsutkkiyfzeyvtyajlvlsewnhksscaimzt 251 | ur:seed/5-7/lpahatcfadehcyetoyioluhddwjltduohddwinbschfzkiaygmmudpcnkklahfoxdksgsgvlrstyvlbsvsaxbsmwenfezturgtlnuecwfehgatksprpytiinki 252 | ur:seed/6-7/lpamatcfadehcyetoyioluhddwiymotofgcemhguskgeflfyfspliorntefgdkykpswzwyrywtpfvwdeecahtdhhvalrnynbtiwnbdctuesabtmneceegwrkkn 253 | ur:seed/7-7/lpatatcfadehcyetoyioluhddwvapratdwlbvltpgsglmdbnmknebkkscymofpkteyvoatjlqdaovesffhylgdimamcyadctgstymddlynpeaeaeaerosssfjl 254 | ur:seed/8-7/lpayatcfadehcyetoyioluhddwtotelphkaewkfrisssiofgkbkpmepychnyrotiztwylogyfdpflbjllppmtyesdylejktifmglendlltrfpfpkeeglchdakp 255 | ur:seed/9-7/lpasatcfadehcyetoyioluhddwmeottiiogmdnayhholprylstdieytohtweknvtwsdifhbwsptadlzsldrpnspscsutkkiyfzeyvtyajlvlsewnhkfxjypdtk 256 | ur:seed/10-7/lpbkatcfadehcyetoyioluhddwdwjyuybdmkiyknftdacyaoqdtkaaiofxhglrvtcpmwwnsemtftosmshpamfeehweurtidmkneordbgcygadturseztzekpgl 257 | ur:seed/11-7/lpbdatcfadehcyetoyioluhddwehdmfycnkblknsvdotwflfldynferlatkkaxcsdsbelrfgtlkshtlffmhldaryhetyrysnpyvelrtygmimlpwddivdytgsti 258 | ur:seed/12-7/lpbnatcfadehcyetoyioluhddwjltduohddwinbschfzkiaygmmudpcnkklahfoxdksgsgvlrstyvlbsvsaxbsmwenfezturgtlnuecwfehgatksprhtwevebg 259 | ur:seed/13-7/lpbtatcfadehcyetoyioluhddwjltduohddwinbschfzkiaygmmudpcnkklahfoxdksgsgvlrstyvlbsvsaxbsmwenfezturgtlnuecwfehgatksprflksylsk 260 | ur:seed/14-7/lpbaatcfadehcyetoyioluhddwylehckclglrkhpnlwpykqdzsldgojoldpyhybzfxtlttpletinsgtdrfqdglwtzehkvlswmhsrwmvdpaclsflbjzctmefdbk 261 | ur:seed/15-7/lpbsatcfadehcyetoyioluhddwknfynsdnzsfzbzuogtykzmihnbweneoxvaeelyrhihiduthkemwndalecwtijzbzgarfvdnletrhseinlsgmjpdnfmwlgytb 262 | ur:seed/16-7/lpbeatcfadehcyetoyioluhddwntknhffwlpnljnghlffrspneaydwcmlgzsvoknnymwnsgoaewtztwnjlptvordgmmdynhhgtwznbynhngloyrktevtmufstd 263 | ur:seed/17-7/lpbyatcfadehcyetoyioluhddwjltduohddwinbschfzkiaygmmudpcnkklahfoxdksgsgvlrstyvlbsvsaxbsmwenfezturgtlnuecwfehgatkspruroxcabe' \ 264 | "$(${SEEDTOOL} --count 300 --ur=50 --parts 10)" 265 | } 266 | 267 | testInFountainUR() 268 | { 269 | assertEquals $'9d347f841a4e2ce6bc886e1aee74d82442b2f7649c606daedbad06cf8f0f73c8e834c2ebb7d2868d75820ab4fb4e45a1004c9f29b8ef2d4d6a94fab0b373615e3bf736a89e9ceb105f2109fb5226d8a29e0d47ee7ed8774f20245ac5f47b95958b1483daa4aaabc9dad616a30bf338b4ef1e971d2cc449bdcc339258f93f7f91a3d067522b085ca6b2f7c72732ce5aed7ae0ef273f13c8d92ffa89b69cac18dd79664032e0f86fe3c1f1596fd2dc582c690f17407d0852932d23798056a424cacae3bfd4e30fe8030f943645fcdf4d86de1b45570778b26692ce461c9053c54a47443dae67bed34624f5acf2eebdf0b0e5283505d25ce6849aa0d0f10b1fdec20d8e35e6b2072c7fe3d84c4e950c989f0a781a92417732e2076fb302e4cc3ff7506a061a011f4cd4952ff6af' \ 270 | "$(${SEEDTOOL} --in ur \ 271 | 'ur:seed/2-7/lpaoatcfadehcyetoyioluhddwlgkplfbkqzzoglfeoyaegsnedtrowsdpgtimmwzspfqdjkhshyfrylenpdnnnswmbeheclaszogmdstpoennbtfljpyaihsn' \ 272 | 'ur:seed/4-7/lpaaatcfadehcyetoyioluhddwmeottiiogmdnayhholprylstdieytohtweknvtwsdifhbwsptadlzsldrpnspscsutkkiyfzeyvtyajlvlsewnhksscaimzt' \ 273 | 'ur:seed/5-7/lpahatcfadehcyetoyioluhddwjltduohddwinbschfzkiaygmmudpcnkklahfoxdksgsgvlrstyvlbsvsaxbsmwenfezturgtlnuecwfehgatksprpytiinki' \ 274 | 'ur:seed/7-7/lpatatcfadehcyetoyioluhddwvapratdwlbvltpgsglmdbnmknebkkscymofpkteyvoatjlqdaovesffhylgdimamcyadctgstymddlynpeaeaeaerosssfjl' \ 275 | 'ur:seed/8-7/lpayatcfadehcyetoyioluhddwtotelphkaewkfrisssiofgkbkpmepychnyrotiztwylogyfdpflbjllppmtyesdylejktifmglendlltrfpfpkeeglchdakp' \ 276 | 'ur:seed/9-7/lpasatcfadehcyetoyioluhddwmeottiiogmdnayhholprylstdieytohtweknvtwsdifhbwsptadlzsldrpnspscsutkkiyfzeyvtyajlvlsewnhkfxjypdtk' \ 277 | 'ur:seed/10-7/lpbkatcfadehcyetoyioluhddwdwjyuybdmkiyknftdacyaoqdtkaaiofxhglrvtcpmwwnsemtftosmshpamfeehweurtidmkneordbgcygadturseztzekpgl' \ 278 | 'ur:seed/14-7/lpbaatcfadehcyetoyioluhddwylehckclglrkhpnlwpykqdzsldgojoldpyhybzfxtlttpletinsgtdrfqdglwtzehkvlswmhsrwmvdpaclsflbjzctmefdbk' \ 279 | 'ur:seed/16-7/lpbeatcfadehcyetoyioluhddwntknhffwlpnljnghlffrspneaydwcmlgzsvoknnymwnsgoaewtztwnjlptvordgmmdynhhgtwznbynhngloyrktevtmufstd' \ 280 | 'ur:seed/17-7/lpbyatcfadehcyetoyioluhddwjltduohddwinbschfzkiaygmmudpcnkklahfoxdksgsgvlrstyvlbsvsaxbsmwenfezturgtlnuecwfehgatkspruroxcabe')" 281 | } 282 | 283 | testOutSSKRUR() 284 | { 285 | assertEquals $'ur:crypto-sskr/taadecgomymwaeadaemdfnpldrprcmtpcnfwztcstaotfsbsadatkspyfg 286 | ur:crypto-sskr/taadecgomymwaeadadkpuopkpmkijzcalkherkiofmjtlafxrtgassrntl 287 | ur:crypto-sskr/taadecgomymwaeadaoglvdolfhemvogaiyksjpvabncphhmsmkjznbdefy' \ 288 | "$(${SEEDTOOL} --out sskr --group 2-of-3 --ur)" 289 | } 290 | 291 | testInSSKRUR() 292 | { 293 | assertEquals $'9d347f841a4e2ce6bc886e1aee74d824' \ 294 | "$(${SEEDTOOL} --in ur ur:crypto-sskr/taadecgomymwaeadaemdfnpldrprcmtpcnfwztcstaotfsbsadatkspyfg ur:crypto-sskr/taadecgomymwaeadaoglvdolfhemvogaiyksjpvabncphhmsmkjznbdefy)" 295 | } 296 | 297 | # Eat all command-line arguments before calling shunit2. 298 | shift $# 299 | # TODO no shunit2 on windows/msys2/mingw64 platform 300 | if [ "$(uname)" == "Darwin" ] || [ "$(uname)" == "Linux" ]; then 301 | . "${SHUNIT2}" 302 | fi 303 | -------------------------------------------------------------------------------- /src/utils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // utils.cpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #include "utils.hpp" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | 18 | using namespace std; 19 | 20 | const string data_to_hex(const ByteVector& in) { 21 | auto hex = "0123456789abcdef"; 22 | string result; 23 | for(auto c: in) { 24 | result.append(1, hex[(c >> 4) & 0xF]); 25 | result.append(1, hex[c & 0xF]); 26 | } 27 | return result; 28 | } 29 | 30 | uint8_t hex_digit_to_bin(char hex) { 31 | if (hex >= '0' && hex <= '9') { 32 | return hex - '0'; 33 | } else if (hex >= 'A' && hex <= 'F') { 34 | return hex - 'A' + 10; 35 | } else if (hex >= 'a' && hex <= 'f') { 36 | return hex - 'a' + 10; 37 | } else { 38 | throw runtime_error("Invalid hex digit"); 39 | } 40 | } 41 | 42 | const ByteVector hex_to_data(const string& hex) { 43 | ByteVector result; 44 | 45 | auto len = hex.length(); 46 | if(len % 2 != 0) { 47 | throw runtime_error("Hex string must have even number of characters."); 48 | } 49 | auto count = len / 2; 50 | result.reserve(count); 51 | for(auto i = 0; i < count; i++) { 52 | auto b1 = hex_digit_to_bin(hex[i * 2]); 53 | auto b2 = hex_digit_to_bin(hex[i * 2 + 1]); 54 | result.push_back((b1 << 4) | b2); 55 | } 56 | 57 | return result; 58 | } 59 | 60 | const ByteVector data_to_base(const ByteVector& buf, size_t base) { 61 | ByteVector result; 62 | result.reserve(buf.size()); 63 | transform(buf.begin(), buf.end(), back_inserter(result), [&](auto b) { return roundf(b / 255.0 * (base - 1)); }); 64 | return result; 65 | } 66 | 67 | const string data_to_alphabet(const ByteVector &in, 68 | size_t base, 69 | string (to_alphabet)(size_t)) 70 | { 71 | string result; 72 | 73 | auto data = data_to_base(in, base); 74 | for(auto b: data) { 75 | auto s = to_alphabet(b); 76 | result.append(s); 77 | } 78 | 79 | return result; 80 | } 81 | 82 | const string data_to_ints(const ByteVector &in, 83 | size_t low, size_t high, const string &separator) 84 | { 85 | if (!(low < high && high <= 255)) { 86 | throw runtime_error("Int conversion range must be in 0 <= low < high <= 255."); 87 | } 88 | size_t base = high - low + 1; 89 | auto data = data_to_base(in, base); 90 | auto count = in.size(); 91 | string result; 92 | for(auto i = 0; i < count; i++) { 93 | if (i > 0) { 94 | result += separator; 95 | } 96 | 97 | result += to_string(data[i] + low); 98 | } 99 | 100 | return result; 101 | } 102 | 103 | const ByteVector digits_to_data(const string& in, size_t low, size_t high) { 104 | ByteVector result; 105 | for(auto c: in) { 106 | int n = c - '0'; 107 | if(n < low || n > high) { 108 | throw runtime_error("Invalid digit."); 109 | } 110 | result.push_back(n); 111 | } 112 | return result; 113 | } 114 | 115 | const string join(const StringVector &strings, const string &separator) { 116 | ostringstream result; 117 | bool first = true; 118 | for(auto s: strings) { 119 | if(!first) { 120 | result << separator; 121 | } 122 | result << s; 123 | first = false; 124 | } 125 | return result.str(); 126 | } 127 | 128 | const StringVector split(const string& s, const char& separator) { 129 | StringVector result; 130 | string buf; 131 | 132 | for(auto c: s) { 133 | if(c != separator) { 134 | buf += c; 135 | } else if(buf.length() > 0) { 136 | result.push_back(buf); 137 | buf = ""; 138 | } 139 | } 140 | 141 | if(buf != "") { 142 | result.push_back(buf); 143 | } 144 | 145 | return result; 146 | } 147 | 148 | const ByteVector sha256(const ByteVector &buf) { 149 | uint8_t digest[SHA256_DIGEST_LENGTH]; 150 | sha256_Raw(buf.data(), buf.size(), digest); 151 | return ByteVector(digest, digest + SHA256_DIGEST_LENGTH); 152 | } 153 | 154 | const string take(const string &s, size_t count) { 155 | auto first = s.begin(); 156 | auto c = min(s.size(), count); 157 | auto last = first + c; 158 | return string(first, last); 159 | } 160 | 161 | int days_since_epoch() { 162 | using namespace std::chrono; 163 | auto today = system_clock::now(); 164 | auto time_since = today.time_since_epoch(); 165 | typedef duration> days; 166 | return duration_cast(time_since).count(); 167 | } 168 | -------------------------------------------------------------------------------- /src/utils.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // utils.hpp 3 | // 4 | // Copyright © 2020 by Blockchain Commons, LLC 5 | // Licensed under the "BSD-2-Clause Plus Patent License" 6 | // 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | typedef std::vector ByteVector; 17 | typedef std::vector StringVector; 18 | 19 | const std::string data_to_hex(const ByteVector& in); 20 | uint8_t hex_digit_to_bin(char hex); 21 | 22 | const ByteVector hex_to_data(const std::string& hex); 23 | 24 | const ByteVector data_to_base(const ByteVector& buf, size_t base); 25 | 26 | const std::string data_to_alphabet(const ByteVector &in, 27 | size_t base, 28 | std::string (to_alphabet)(size_t)); 29 | 30 | const std::string data_to_ints(const ByteVector &in, 31 | size_t low, size_t high, const std::string &separator); 32 | 33 | const ByteVector digits_to_data(const std::string& in, size_t low, size_t high); 34 | 35 | const std::string join(const StringVector &strings, const std::string &separator); 36 | const StringVector split(const std::string& s, const char& separator); 37 | 38 | const ByteVector sha256(const ByteVector &buf); 39 | 40 | template 41 | const std::vector take(const std::vector &buf, size_t count) { 42 | auto first = buf.begin(); 43 | auto c = std::min(buf.size(), count); 44 | auto last = first + c; 45 | return std::vector(first, last); 46 | } 47 | 48 | const std::string take(const std::string &s, size_t count); 49 | 50 | template 51 | void append(std::vector& target, const std::vector& source) { 52 | target.insert(target.end(), source.begin(), source.end()); 53 | } 54 | 55 | int days_since_epoch(); 56 | 57 | template 58 | const std::vector flatten(const std::vector>& source) { 59 | std::vector result; 60 | for(auto item: source) { 61 | append(result, item); 62 | } 63 | return result; 64 | } 65 | --------------------------------------------------------------------------------