Compare commits

...

90 commits
0.9 ... master

Author SHA1 Message Date
Frank Denis
108ea640ba Require Zig 0.14 2025-03-11 19:06:46 +01:00
Frank Denis
c7d965e43a Update .gitignore 2025-03-11 19:04:58 +01:00
Frank Denis
428c18e08a Zig 0.14 compat 2025-03-11 19:04:40 +01:00
Frank Denis
32038530b7 Add a note about signify compatibility
Fixes #159
2025-03-11 18:43:41 +01:00
Chad Dougherty
e9631e8c67
Add a note in the man page about signify compatibility (#159)
based nearly verbatim on @jedisct1's explanation in the discussion of #59
2025-03-11 18:40:49 +01:00
Frank Denis
74365c0f51 Normalize Markdown files 2025-03-11 18:31:43 +01:00
Frank Denis
d5a2f02bc0 Look at possible include/lib paths for linuxbrew
Fixes #156
2025-01-29 23:05:34 +01:00
Frank Denis
4dd6fbf632 Use a list for possible include paths to be consistent with libraries 2025-01-29 23:02:34 +01:00
Frank Denis
41306e3e42 No need to set headerpad_max_install_names when linking statically 2025-01-29 18:28:41 +01:00
Frank Denis
090cc4752c Set headerpad_max_install_names only when linking libsodium 2025-01-29 18:27:40 +01:00
Rui Chen
b5cf334b42
build: fix mach-o relocation (#155)
Signed-off-by: Rui Chen <rui@chenrui.dev>
2025-01-29 18:27:25 +01:00
Frank Denis
c684406e21 Don't include nonexistent library paths
Introduced in 101e90a668 to make
Minisign build with Zig 0.13.

Fixes #153
2025-01-18 14:46:57 +01:00
Frank Denis
29a07eade0 Add compatibility with 32-bit targets (webassembly) 2025-01-16 13:36:56 +01:00
Frank Denis
90d46db240 Add the ability to override the libsodium install dirs 2025-01-16 12:55:52 +01:00
Frank Denis
101e90a668 Allow compilation with Zig 0.13 as well as 0.14
Fixes #150
2025-01-16 00:54:22 +01:00
Frank Denis
c165362385 Move libzodium files to a dedicated directory 2025-01-15 23:42:24 +01:00
Frank Denis
1c44ef601e Regen man page 2025-01-15 23:42:04 +01:00
Frank Denis
3c889ce7f3 Add a section title 2025-01-15 23:27:20 +01:00
Frank Denis
b85e15d45a Add build.zig.zon 2025-01-15 22:46:54 +01:00
Frank Denis
9896d072d4 Bump 2025-01-15 22:46:54 +01:00
Frank Denis
b393ff47b1 Let people compile with ReleaseFast if they want to 2025-01-15 22:46:54 +01:00
Frank Denis
c084f9ca38 without_libsodium -> without-libsodium 2025-01-15 22:46:54 +01:00
Frank Denis
c1c452560f Nits 2025-01-15 22:46:51 +01:00
Frank Denis
e0e86b4e4f Add -Dstatic 2025-01-15 22:46:51 +01:00
Frank Denis
12333fd7d1 Minisign is 10 years old 2025-01-15 22:46:51 +01:00
Frank Denis
952225f9b7 Import zodium.h 2025-01-15 22:46:51 +01:00
Frank Denis
e43b9ff13b Make libsodium optional 2025-01-15 22:11:52 +01:00
Frank Denis
e640be4b8f Indent 2025-01-15 22:07:37 +01:00
Frank Denis
a1c07cc277 Leverage root_module.linkSystemLibrary() 2025-01-15 21:03:56 +01:00
Frank Denis
285b53d52c Mention where the compiled binary is 2025-01-15 21:03:49 +01:00
Frank Denis
28612a431a Add issues.yml 2024-12-31 14:58:15 +01:00
Frank Denis
cbc79b3ece defineCMacro -> root_module.addCMacro 2024-12-20 12:21:03 +01:00
Frank Denis
55320cc84c 2024 2024-12-11 18:46:14 +01:00
Frank Denis
868785690f Add a Docker usage example
Fixes #132
2024-12-11 18:45:20 +01:00
Frank Denis
45478e1dd6 Udpate for Zig 0.13 2024-05-09 21:46:20 +02:00
Ryan Castellucci
996ea4fee3
exclude other unneeded code for VERIFY_ONLY (#139) 2024-04-02 08:11:27 +02:00
Frank Denis
573988d235 Update for zig-master 2024-01-04 12:24:31 +01:00
Isaac Yonemoto
5f96819f44
Add Elixir to minisign implementations (#138) 2023-12-18 18:50:08 +01:00
Frank Denis
ef2db96ae0 Breaking: wero-pad key identifiers
Fixes #137
2023-12-17 22:04:43 +01:00
Frank Denis
7d1116c5cc Zig 0.12 compat 2023-11-20 19:13:22 +01:00
Frank Denis
8aef018182 Update for Zig 0.11 2023-08-12 11:21:37 +02:00
Frank Denis
709fed6b73 Build script 2023-01-17 11:48:15 +01:00
Frank Denis
05a0cd435d Remove Travis 2023-01-17 11:40:20 +01:00
Frank Denis
444ef2dca9 Remove unused var 2023-01-16 22:42:27 +01:00
Frank Denis
ee46615226 Zeroize seckey_struct early 2023-01-16 21:24:08 +01:00
Frank Denis
12fd90b6fe Update man page 2023-01-16 21:18:39 +01:00
Frank Denis
ef445ab928 2023 2023-01-16 21:16:52 +01:00
Frank Denis
3f1df52db4 Warn about -C -W implications before it's too late 2023-01-16 21:16:38 +01:00
Frank Denis
506ac9ce3e Simplify usage without key encryption 2023-01-16 21:12:16 +01:00
Frank Denis
27bff8a1f5 Use CMAKE_BUILD_TYPE=MinSizeRel 2023-01-16 20:50:57 +01:00
Frank Denis
80defb2a99 Bump 2023-01-16 20:46:34 +01:00
Frank Denis
6040047c27 seckey_chk() actually computes chk 2023-01-16 20:46:34 +01:00
Frank Denis
16624abf2e Add the ability to change the password of a secret key
Fixes #110
2023-01-16 20:39:56 +01:00
Frank Denis
6ccd801dbc Allow seckey_load() to optionally return a copy of the key comment 2023-01-16 20:04:16 +01:00
Frank Denis
41938e99f5 Move key encryption/decryption code to dedicated functions 2023-01-16 19:45:00 +01:00
Frank Denis
a536c178ab Format 2023-01-16 19:40:34 +01:00
Frank Denis
94e18a72d8 Move variables to a local context 2023-01-16 19:38:39 +01:00
Frank Denis
d870938ae5 Reorder commands for clarity 2023-01-16 19:21:19 +01:00
Frank Denis
d2afa89fe7 Update usage 2023-01-16 19:15:53 +01:00
Frank Denis
c33051dec3 Update usage 2023-01-16 19:03:20 +01:00
Frank Denis
cb2fc2ce7c Add a flag to allow secret keys to be unencrypted
https://github.com/ziglang/zig/issues/4945
2023-01-16 18:50:36 +01:00
Frank Denis
0fccaf94e2 Require cmake 2.8.12 2023-01-16 18:43:18 +01:00
Frank Denis
a26f2c8e5d Update build.zig for zig 0.10 2023-01-11 01:27:48 +01:00
Frank Denis
a2c8848418 Add cosign public key
Fixes #121
2022-06-10 14:17:52 +02:00
Frank Denis
4b2df2ee07 Bail out if fgets() output is not \n terminated when it should
Fixes #116
2022-02-20 10:50:37 +01:00
Frank Denis
b81f3d4065 Add paths for Homebrew on Apple Silicon 2021-11-30 09:22:24 +01:00
Frank Denis
e74428c464 Update man page
Fixes #106
2021-10-25 00:53:09 +02:00
Frank Denis
aa99a5c417 Document -f option 2021-10-09 17:47:16 +02:00
Frank Denis
614fd57665 Define _GNU_SOURCE 2021-10-09 15:54:09 +02:00
Frank Denis
503f722ac3 Suggest release-safe 2021-10-09 15:34:41 +02:00
Frank Denis
40dd5acf36 Bump CMakeList version 2021-10-09 15:04:03 +02:00
Frank Denis
da6c6e7f77 Remove final stop 2021-10-09 14:00:23 +02:00
Frank Denis
a02e9e608b Bump version 2021-10-08 22:15:00 +02:00
Frank Denis
a832bbc270 Autoformat 2021-10-08 22:08:02 +02:00
Frank Denis
dfb7dda9dc Add -H / -l options 2021-10-08 19:31:50 +02:00
Frank Denis
b653798d66 Remove workaround for really ancient libsodium versions 2021-10-08 15:06:06 +02:00
Frank Denis
52ccad8685 Add build.zig file 2021-10-08 15:04:21 +02:00
Frank Denis
f6965a0858 Fix compilation with VERIFY_ONLY 2021-10-08 14:40:58 +02:00
Frank Denis
1e050e7d0a Always prehash, add this to the default trusted comment 2021-10-08 14:39:33 +02:00
Frank Denis
c9ba80b656 Add minizign 2021-04-15 17:42:03 +02:00
Frank Denis
1cbcac9644 Error out if the same option is specified multiple times
Fixes #87
2021-04-04 19:24:12 +02:00
Frank Denis
f3e97d838f up 2021-03-04 18:44:27 +01:00
Frank Denis
b9349929fb Add the Go rewrite of minisign 2021-03-04 18:41:59 +01:00
Frank Denis
7edc350137 Add py-minisign 2021-02-27 01:32:24 +01:00
Frank Denis
d5b74ae86e up 2021-02-27 01:32:22 +01:00
Abu Sakib
121cf06e9b
Fix example of how to verify with pubkey (#89) 2020-11-07 22:37:19 +01:00
Frank Denis
1a7cc6c860
Merge pull request #80 from soatok/patch-1
Add link to PHP implementation
2020-08-08 08:25:21 +02:00
Soatok Dreamseeker
246d542e37
Add link to PHP implementation 2020-08-07 19:54:10 -04:00
Frank Denis
bb81665e20 Remove duplicate va_end() on error path 2020-07-17 16:08:50 +02:00
Frank Denis
82913c2b64 Add CodeQL scan 2020-06-11 10:27:28 +02:00
24 changed files with 1184 additions and 615 deletions

165
.clang-format Normal file
View file

@ -0,0 +1,165 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: true
AlignConsecutiveBitFields: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: true
AlignOperands: true
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: TopLevelDefinitions
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: WebKit
BreakBeforeInheritanceComma: true
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 100
CommentPragmas: "^ IWYU pragma:"
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: true
DisableFormat: false
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: true
FixNamespaceComments: false
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
StatementAttributeLikeMacros:
- Q_EMIT
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: ".*"
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: "(Test)?$"
IncludeIsMainSourceRegex: ""
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: AfterHash
IndentExternBlock: AfterExternBlock
IndentRequires: false
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: Inner
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
---

32
.github/workflows/codeql-analysis.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: "CodeQL scan"
on:
push:
pull_request:
schedule:
- cron: '0 16 * * 2'
jobs:
CodeQL-Build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
fetch-depth: 2
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
- run: sudo apt-get install -qy libsodium-dev
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
- name: Autobuild
uses: github/codeql-action/autobuild@v1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

17
.github/workflows/issues.yml vendored Normal file
View file

@ -0,0 +1,17 @@
name: Close inactive issues
on:
schedule:
- cron: "30 1 * * *"
jobs:
close-issues:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
repo-token: ${{ secrets.GITHUB_TOKEN }}

3
.gitignore vendored
View file

@ -23,4 +23,5 @@ CMakeFiles
Makefile
cmake_install.cmake
minisign
.zig-cache
zig-out

View file

@ -1,43 +0,0 @@
sudo: required
language: c
os:
- linux
compiler:
- gcc
before_script:
- git clone https://github.com/jedisct1/libsodium.git --branch=stable
- cd libsodium
- env CPPFLAGS=-DED25519_NONDETERMINISTIC ./configure --disable-dependency-tracking
- make -j$(nproc)
- sudo make install
- sudo ldconfig
- cd ..
script:
- rm -fr build
- mkdir build
- cd build
- cmake ..
- make -j$(nproc)
- cd ..
- rm -fr build
- mkdir build
- cd build
- cmake -D STATIC_LIBSODIUM=1 ..
- make -j$(nproc)
- cd ..
- rm -fr build
- mkdir build
- cd build
- cmake -D BUILD_STATIC_EXECUTABLES=1 ..
- make -j$(nproc)
- cd ..
matrix:
- fast_finish: true

View file

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 2.8)
cmake_minimum_required(VERSION 3.10)
project(minisign C)
@ -7,7 +7,7 @@ set(CPACK_PACKAGE_VENDOR "Frank Denis")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "9")
set(CPACK_PACKAGE_VERSION_MINOR "12")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(
CPACK_SOURCE_PACKAGE_FILE_NAME

View file

@ -7,7 +7,7 @@ RUN apk add --no-cache upx ||:
RUN curl https://download.libsodium.org/libsodium/releases/LATEST.tar.gz | tar xzvf - && cd libsodium-stable && env CFLAGS="-Os" CPPFLAGS="-DED25519_NONDETERMINISTIC=1" ./configure --disable-dependency-tracking && make -j$(nproc) check && make install && cd .. && rm -fr libsodium-stable
COPY ./ ./
RUN mkdir build && cd build && cmake -D BUILD_STATIC_EXECUTABLES=1 .. && make -j$(nproc)
RUN mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DBUILD_STATIC_EXECUTABLES=1 .. && make -j$(nproc)
RUN upx --lzma build/minisign ||:
FROM scratch

View file

@ -1,7 +1,7 @@
ISC LICENSE.
/*
* Copyright (c) 2015-2020
* Copyright (c) 2015-2025
* Frank Denis <j at pureftpd dot org>
*
* Permission to use, copy, modify, and/or distribute this software for any

112
README.md
View file

@ -1,6 +1,6 @@
![CodeQL scan](https://github.com/jedisct1/minisign/workflows/CodeQL%20scan/badge.svg)
Minisign
========
# Minisign
Minisign is a dead simple tool to sign files and verify signatures.
@ -12,14 +12,39 @@ public key:
RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3
Compilation / installation
--------------------------
## Compilation / installation
## Building with Zig
Dependencies:
* [libsodium](https://libsodium.org/)
* cmake
* pkg-config
- [libsodium](https://libsodium.org/) (_optional_)
- [zig](https://ziglang.org)
Compilation with libsodium, dynamically linked (libsodium will need to be installed on the system for the command to run):
$ zig build -Doptimize=ReleaseSmall
Compilation with libsodium, statically linked (libsodium will only be needed for compilation):
$ zig build -Doptimize=ReleaseSmall -Dstatic
Compilation without libsodium, no dependencies required:
$ zig build -Doptimize=ReleaseSmall -Dwithout-libsodium
The resulting binary can be found in `zig-out/bin/minisign`.
In all these examples, `ReleaseFast` can be replaced with `ReleaseSmall` to favor speed over size.
## Building with cmake and gcc or clang:
Dependencies:
- [libsodium](https://libsodium.org/) (_required_)
- cmake
- pkg-config
- gcc or clang
Compilation:
@ -37,6 +62,8 @@ or:
$ cmake -D BUILD_STATIC_EXECUTABLES=1 ..
## Pre-built packages
Minisign is also available in Homebrew:
$ brew install minisign
@ -49,38 +76,57 @@ Minisign is also available in chocolatey on Windows:
$ choco install minisign
Minisign is also available on Ubuntu as a PPA:
$ [sudo] add-apt-repository ppa:dysfunctionalprogramming/minisign
Minisign is also available with docker:
$ docker run -i --rm jedisct1/minisign
Additional tools, libraries and implementations
-----------------------------------------------
For example, verifying a signature using the docker image can be done
with:
* [minisign-misc](https://github.com/JayBrown/minisign-misc) is a very
nice set of workflows and scripts for macOS to verify and sign files
with minisign.
* [go-minisign](https://github.com/jedisct1/go-minisign) is a small module
in Go to verify Minisign signatures.
* [rust-minisign](https://github.com/jedisct1/rust-minisign) is a Minisign
library written in pure Rust, that can be embedded in other applications.
* [rsign2](https://github.com/jedisct1/rsign2) is a reimplementation of
the command-line tool in Rust.
* [minisign-verify](https://github.com/jedisct1/rust-minisign-verify) is
a small Rust crate to verify Minisign signatures.
* [minisign-net](https://github.com/bitbeans/minisign-net) is a .NET library
to handle and create Minisign signatures.
* [minisign](https://github.com/chm-diederichs/minisign) a Javascript
implementation.
* WebAssembly implementations of [rsign2](https://wapm.io/package/jedisct1/rsign2)
and [minisign-cli](https://wapm.io/package/jedisct1/minisign) are available on
WAPM.
$ docker run -v .:/minisign -e HOME=/minisign -w /minisign \
-it --rm jedisct1/minisign \
-Vm file_to_verify -p minisign.pub
Signature determinism
---------------------
The image can be verified with the following cosign public key:
```text
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExjZWrlc6c58W7ZzmQnx6mugty99C
OQTDtJeciX9LF9hEbs1J1fzZHRdRhV4OTqcq0jTW9PXnrSSZlk1fbkE/5w==
-----END PUBLIC KEY-----
```
## Additional tools, libraries and implementations
- [minizign](https://github.com/jedisct1/zig-minisign) is a compact
implementation in Zig, that can also use ssh-encoded keys.
- [minisign-misc](https://github.com/JayBrown/minisign-misc) is a very
nice set of workflows and scripts for macOS to verify and sign files
with minisign.
- [go-minisign](https://github.com/jedisct1/go-minisign) is a small module
in Go to verify Minisign signatures.
- [rust-minisign](https://github.com/jedisct1/rust-minisign) is a Minisign
library written in pure Rust, that can be embedded in other applications.
- [rsign2](https://github.com/jedisct1/rsign2) is a reimplementation of
the command-line tool in Rust.
- [minisign (go)](https://github.com/aead/minisign) is a rewrite of Minisign
in the Go language. It reimplements the CLI but can also be used as a library.
- [minisign-verify](https://github.com/jedisct1/rust-minisign-verify) is
a small Rust crate to verify Minisign signatures.
- [minisign-net](https://github.com/bitbeans/minisign-net) is a .NET library
to handle and create Minisign signatures.
- [minisign](https://github.com/chm-diederichs/minisign) a Javascript
implementation.
- WebAssembly implementations of [rsign2](https://wapm.io/package/jedisct1/rsign2)
and [minisign-cli](https://wapm.io/package/jedisct1/minisign) are available on
WAPM.
- [minisign-php](https://github.com/soatok/minisign-php) is a PHP implementation.
- [py-minisign](https://github.com/x13a/py-minisign) is a Python
implementation.
- [minisign](https://hexdocs.pm/minisign/Minisign.html) is an Elixir implementation
(verification only)
## Signature determinism
This implementation uses deterministic signatures, unless libsodium
was compiled with the `ED25519_NONDETERMINISTIC` macro defined. This

4
build-dist-package.sh Executable file
View file

@ -0,0 +1,4 @@
#! /bin/sh
tar czpvf minisign-0.12.tar.gz $(git ls-files)
minisign -Sm minisign-0.12.tar.gz

80
build.zig Normal file
View file

@ -0,0 +1,80 @@
const builtin = @import("builtin");
const std = @import("std");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const use_libzodium = b.option(bool, "without-libsodium", "Use the zig standard library instead of libsodium") orelse false;
const use_static_linking = b.option(bool, "static", "Statically link the binary") orelse false;
const minisign = b.addExecutable(.{
.name = "minisign",
.target = target,
.optimize = optimize,
.strip = true,
});
if (builtin.zig_version.major == 0 and builtin.zig_version.minor < 14) {
@compileError("Building requires Zig 0.14.0 or later");
}
// fix Mach-O relocation
minisign.headerpad_max_install_names = true;
minisign.linkLibC();
if (use_libzodium) {
var libzodium = lib: {
const libzodium_mod = b.createModule(.{
.root_source_file = b.path("src/libzodium/libzodium.zig"),
.target = target,
.optimize = optimize,
});
break :lib b.addStaticLibrary(.{
.name = "zodium",
.root_module = libzodium_mod,
.strip = true,
});
};
libzodium.linkLibC();
b.installArtifact(libzodium);
minisign.root_module.addCMacro("LIBZODIUM", "1");
minisign.linkLibrary(libzodium);
} else {
var override_pkgconfig = false;
if (std.posix.getenv("LIBSODIUM_INCLUDE_PATH")) |path| {
minisign.addSystemIncludePath(.{ .cwd_relative = path });
override_pkgconfig = true;
}
if (std.posix.getenv("LIBSODIUM_LIB_PATH")) |path| {
minisign.addLibraryPath(.{ .cwd_relative = path });
override_pkgconfig = true;
}
for ([_][]const u8{ "/opt/homebrew/include", "/home/linuxbrew/.linuxbrew/include", "/usr/local/include" }) |path| {
std.fs.accessAbsolute(path, .{}) catch continue;
minisign.addSystemIncludePath(.{ .cwd_relative = path });
}
for ([_][]const u8{ "/opt/homebrew/lib", "/home/linuxbrew/.linuxbrew/lib", "/usr/local/lib" }) |path| {
std.fs.accessAbsolute(path, .{}) catch continue;
minisign.addLibraryPath(.{ .cwd_relative = path });
}
if (!use_static_linking) {
minisign.headerpad_max_install_names = true; // required to compile using Homebrew, see https://github.com/jedisct1/minisign/pull/155
}
minisign.root_module.linkSystemLibrary(
"sodium",
.{
.use_pkg_config = if (override_pkgconfig) .no else .yes,
.preferred_link_mode = if (use_static_linking) .static else .dynamic,
},
);
}
minisign.addIncludePath(b.path("src"));
minisign.root_module.addCMacro("_GNU_SOURCE", "1");
const source_files = &.{ "src/base64.c", "src/get_line.c", "src/helpers.c", "src/minisign.c" };
minisign.addCSourceFiles(.{ .files = source_files });
b.installArtifact(minisign);
}

13
build.zig.zon Normal file
View file

@ -0,0 +1,13 @@
.{
.name = .minisign,
.version = "0.12.0",
.fingerprint = 0x280456c1fd373c55,
.paths = .{
"LICEMSE",
"README.md",
"build.zig",
"build.zig.zon",
"src",
"share",
},
}

4
cosign.pub Normal file
View file

@ -0,0 +1,4 @@
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExjZWrlc6c58W7ZzmQnx6mugty99C
OQTDtJeciX9LF9hEbs1J1fzZHRdRhV4OTqcq0jTW9PXnrSSZlk1fbkE/5w==
-----END PUBLIC KEY-----

View file

@ -1,22 +1,25 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
.TH "MINISIGN" "1" "June 2020" "" ""
.TH "MINISIGN" "1" "March 2025" "" ""
.
.SH "NAME"
\fBminisign\fR \- A dead simple tool to sign files and verify signatures\.
.
.SH "SYNOPSIS"
\fBminisign\fR \-G [\-p pubkey] [\-s seckey]
\fBminisign\fR \-G [\-p pubkey_file] [\-s seckey_file] [\-W]
.
.P
\fBminisign\fR \-S [\-H] [\-x sigfile] [\-s seckey] [\-c untrusted_comment] [\-t trusted_comment] \-m file [file \.\.\.]
\fBminisign\fR \-R [\-s seckey_file] [\-p pubkey_file]
.
.P
\fBminisign\fR \-V [\-x sigfile] [\-p pubkeyfile | \-P pubkey] [\-o] [\-q] \-m file
\fBminisign\fR \-C [\-s seckey_file] [\-W]
.
.P
\fBminisign\fR \-R \-s seckey \-p pubkeyfile
\fBminisign\fR \-S [\-H] [\-x sig_file] [\-s seckey_file] [\-c untrusted_comment] [\-t trusted_comment] \-m file [file \.\.\.]
.
.P
\fBminisign\fR \-V [\-x sig_file] [\-p pubkey_file | \-P pubkey] [\-o] [\-q] \-m file
.
.SH "DESCRIPTION"
\fBMinisign\fR is a dead simple tool to sign files and verify signatures\.
@ -32,6 +35,14 @@ These options control the actions of \fBminisign\fR\.
Generate a new key pair
.
.TP
\fB\-C\fR
Change/remove the password of a secret key
.
.TP
\fB\-R\fR
Recreate a public key file from a secret key file
.
.TP
\fB\-S\fR
Sign files
.
@ -40,6 +51,14 @@ Sign files
Verify that a signature is valid for a given file
.
.TP
\fB\-H\fR
Requires the input to be prehashed
.
.TP
\fB\-l\fR
Sign using the legacy format
.
.TP
\fB\-m <file>\fR
File to sign/verify
.
@ -48,11 +67,7 @@ File to sign/verify
Combined with \-V, output the file content after verification
.
.TP
\fB\-H\fR
Combined with \-S, pre\-hash in order to sign large files
.
.TP
\fB\-p <pubkeyfile>\fR
\fB\-p <pubkey_file>\fR
Public key file (default: \./minisign\.pub)
.
.TP
@ -60,11 +75,15 @@ Public key file (default: \./minisign\.pub)
Public key, as a base64 string
.
.TP
\fB\-s <seckey>\fR
\fB\-s <seckey_file>\fR
Secret key file (default: ~/\.minisign/minisign\.key)
.
.TP
\fB\-x <sigfile>\fR
\fB\-W\fR
Do not encrypt/decrypt the secret key with a password
.
.TP
\fB\-x <sig_file>\fR
Signature file (default: <file>\.minisig)
.
.TP
@ -84,10 +103,6 @@ Quiet mode, suppress output
Pretty quiet mode, only print the trusted comment
.
.TP
\fB\-R\fR
Recreate a public key file from a secret key file
.
.TP
\fB\-f\fR
Force\. Combined with \-G, overwrite a previous key pair
.
@ -123,7 +138,7 @@ The secret key is loaded from \fB${MINISIGN_CONFIG_DIR}/minisign\.key\fR, \fB~/\
Verifying a file
.
.P
$ \fBminisign\fR \-Vm myfile\.txt \-p <pubkey>
$ \fBminisign\fR \-Vm myfile\.txt \-P <pubkey>
.
.P
or
@ -137,53 +152,17 @@ This requires the signature \fBmyfile\.txt\.minisig\fR to be present in the same
.P
The public key can either reside in a file (\fB\./minisign\.pub\fR by default) or be directly specified on the command line\.
.
.SH "Notes"
\fBTrusted comments\fR
.SH "NOTES"
Signature files include an untrusted comment line that can be freely modified even after the signature is created\.
.
.P
Signature files include an untrusted comment line that can be freely modified, even after signature creation\.
They also include a second comment line that cannot be modified without the secret key\.
.
.P
They also include a second comment line, that cannot be modified without the secret key\.
Trusted comments can be used to add instructions or application\-specific metadata such as the intended file name, timestamps, resource identifiers, or version numbers to prevent downgrade attacks\.
.
.P
Trusted comments can be used to add instructions or application\-specific metadata (intended file name, timestamps, resource identifiers, version numbers to prevent downgrade attacks)\.
.
.P
\fBCompatibility with OpenBSD signify\fR
.
.P
Signatures written by \fBminisign\fR can be verified using OpenBSD\'s \fBsignify\fR tool: public key files and signature files are compatible\.
.
.P
However, \fBminisign\fR uses a slightly different format to store secret keys\.
.
.P
\fBMinisign\fR signatures include trusted comments in addition to untrusted comments\. Trusted comments are signed, thus verified, before being displayed\.
.
.P
This adds two lines to the signature files, that signify silently ignores\.
.
.P
\fBPre\-hashing\fR
.
.P
By default, signing and verification require as much memory as the size of the file\.
.
.P
Since \fBMinisign 0\.6\fR, huge files can be signed and verified with very low memory requirements, by pre\-hashing the content\.
.
.P
The \-H command\-line switch, in combination with \-S, generates a pre\-hashed signature (HashEdDSA):
.
.P
$ \fBminisign\fR \-SHm myfile\.txt
.
.P
Verification of such a signature doesn\'t require any specific switch: the appropriate algorithm will automatically be detected\.
.
.P
Signatures generated that way are not compatible with OpenBSD\'s \fBsignify\fR tool and are not compatible with \fBMinisign\fR versions prior to 0\.6\.
OpenBSD\'s \fBsignify(1)\fR is conceptually similar to Minisign\. Minisign creates signatures that can be verified by \fBsignify\fR; however, signatures created by \fBsignify\fR cannot be verified with Minisign because Minisign expects a trusted comment section to be present\. Trusted comments are crucial for describing what has been signed, in addition to merely confirming that a signature exists\.
.
.SH "AUTHOR"
Frank Denis (github [at] pureftpd [dot] org)

View file

@ -5,44 +5,70 @@
#include "base64.h"
unsigned char *
b64_to_bin(unsigned char * const bin, const char *b64,
size_t bin_maxlen, size_t b64_len, size_t * const bin_len_p)
b64_to_bin(unsigned char *const bin, const char *b64, size_t bin_maxlen, size_t b64_len,
size_t *const bin_len_p)
{
#define REV64_EOT 128U
#define REV64_NONE 64U
#define REV64_PAD '='
#define REV64_NONE 64U
#define REV64_PAD '='
static const unsigned char rev64chars[256] = {
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, 62U, REV64_NONE, REV64_NONE, REV64_NONE, 63U, 52U, 53U, 54U, 55U, 56U, 57U, 58U, 59U, 60U, 61U, REV64_NONE, REV64_NONE, REV64_NONE, REV64_EOT, REV64_NONE, REV64_NONE, REV64_NONE, 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U,
8U, 9U, 10U, 11U, 12U, 13U, 14U, 15U, 16U, 17U, 18U, 19U, 20U, 21U, 22U, 23U, 24U, 25U, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, 26U, 27U, 28U, 29U, 30U, 31U, 32U, 33U, 34U, 35U, 36U, 37U, 38U, 39U, 40U, 41U, 42U,
43U, 44U, 45U, 46U, 47U, 48U, 49U, 50U, 51U, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, 62U, REV64_NONE, REV64_NONE, REV64_NONE, 63U, 52U,
53U, 54U, 55U, 56U, 57U, 58U, 59U,
60U, 61U, REV64_NONE, REV64_NONE, REV64_NONE, REV64_EOT, REV64_NONE,
REV64_NONE, REV64_NONE, 0U, 1U, 2U, 3U, 4U,
5U, 6U, 7U, 8U, 9U, 10U, 11U,
12U, 13U, 14U, 15U, 16U, 17U, 18U,
19U, 20U, 21U, 22U, 23U, 24U, 25U,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, 26U,
27U, 28U, 29U, 30U, 31U, 32U, 33U,
34U, 35U, 36U, 37U, 38U, 39U, 40U,
41U, 42U, 43U, 44U, 45U, 46U, 47U,
48U, 49U, 50U, 51U, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE
};
const unsigned char *b64_u = (const unsigned char *) b64;
unsigned char *bin_w = bin;
unsigned char mask = 0U;
unsigned char t0 = 0, t1 = 0 , t2 = 0, t3 = 0;
unsigned char mask = 0U;
unsigned char t0 = 0, t1 = 0, t2 = 0, t3 = 0;
uint32_t t = 0;
size_t i;
if (b64_len % 4U != 0U || (i = b64_len / 4U) <= 0U || bin_maxlen < i * 3U -
(b64_u[b64_len - 1U] == REV64_PAD) - (b64_u[b64_len - 2U] == REV64_PAD)) {
if (b64_len % 4U != 0U || (i = b64_len / 4U) <= 0U ||
bin_maxlen <
i * 3U - (b64_u[b64_len - 1U] == REV64_PAD) - (b64_u[b64_len - 2U] == REV64_PAD)) {
return NULL;
}
while (i-- > 0U) {
t0 = rev64chars[*b64_u++];
t1 = rev64chars[*b64_u++];
t2 = rev64chars[*b64_u++];
t3 = rev64chars[*b64_u++];
t = t3 | ((uint32_t) t2 << 6) | ((uint32_t) t1 << 12) |
((uint32_t) t0 << 18);
t0 = rev64chars[*b64_u++];
t1 = rev64chars[*b64_u++];
t2 = rev64chars[*b64_u++];
t3 = rev64chars[*b64_u++];
t = t3 | ((uint32_t) t2 << 6) | ((uint32_t) t1 << 12) | ((uint32_t) t0 << 18);
mask = t0 | t1 | t2 | t3;
if ((mask & (REV64_NONE | REV64_EOT)) != 0U) {
if ((mask & REV64_NONE) != 0U || i > 0U) {
@ -69,8 +95,8 @@ b64_to_bin(unsigned char * const bin, const char *b64,
return bin;
}
char *bin_to_b64(char * const b64, const unsigned char *bin,
size_t b64_maxlen, size_t bin_len)
char *
bin_to_b64(char *const b64, const unsigned char *bin, size_t b64_maxlen, size_t bin_len)
{
#define B64_PAD '='

View file

@ -4,12 +4,10 @@
#include <stddef.h>
unsigned char *b64_to_bin(unsigned char * const bin, const char *b64,
size_t bin_maxlen, size_t b64_len,
size_t * const bin_len_p);
unsigned char *b64_to_bin(unsigned char *const bin, const char *b64, size_t bin_maxlen,
size_t b64_len, size_t *const bin_len_p);
char *bin_to_b64(char * const b64, const unsigned char *bin,
size_t b64_maxlen, size_t bin_len);
char *bin_to_b64(char *const b64, const unsigned char *bin, size_t b64_maxlen, size_t bin_len);
#define B64_MAX_LEN_FROM_BIN_LEN(X) (((X) + 2) / 3 * 4 + 1)
#define BIN_MAX_LEN_FROM_B64_LEN(X) ((X) / 4 * 3)

View file

@ -1,6 +1,6 @@
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
# include <sys/types.h>
# include <sys/types.h>
#endif
#include <assert.h>
@ -10,19 +10,19 @@
#include <string.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
# include <fcntl.h>
# include <poll.h>
# include <termios.h>
# include <unistd.h>
# include <fcntl.h>
# include <poll.h>
# include <termios.h>
# include <unistd.h>
#elif defined(_WIN32)
# include <windows.h>
# include <windows.h>
#endif
#include "get_line.h"
#include "helpers.h"
#ifndef TCSAFLUSH
# define TCSAFLUSH 0
# define TCSAFLUSH 0
#endif
#ifndef VERIFY_ONLY
@ -33,7 +33,7 @@ disable_echo(void)
fflush(stdout);
fflush(stderr);
# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
{
struct termios p;
@ -43,15 +43,15 @@ disable_echo(void)
p.c_lflag &= ~ECHO;
tcsetattr(0, TCSAFLUSH, &p);
}
# elif defined(_WIN32)
# elif defined(_WIN32)
{
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode = 0;
DWORD mode = 0;
GetConsoleMode(handle, &mode);
SetConsoleMode(handle, mode & ~ENABLE_ECHO_INPUT);
}
# endif
# endif
}
static void
@ -60,7 +60,7 @@ enable_echo(void)
fflush(stdout);
fflush(stderr);
# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
{
struct termios p;
@ -70,15 +70,15 @@ enable_echo(void)
p.c_lflag |= ECHO;
tcsetattr(0, TCSAFLUSH, &p);
}
# elif defined(_WIN32)
# elif defined(_WIN32)
{
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode = 0;
DWORD mode = 0;
GetConsoleMode(handle, &mode);
SetConsoleMode(handle, mode | ENABLE_ECHO_INPUT);
}
# endif
# endif
}
int

View file

@ -1,10 +1,10 @@
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/types.h>
#elif defined(_WIN32)
# include <direct.h>
# include <direct.h>
#endif
#include <errno.h>
@ -14,7 +14,11 @@
#include <stdlib.h>
#include <string.h>
#include <sodium.h>
#ifdef LIBZODIUM
# include "libzodium/sodium.h"
#else
# include <sodium.h>
#endif
#include "base64.h"
#include "helpers.h"
@ -22,10 +26,9 @@
uint64_t
le64_load(const unsigned char *p)
{
return ((uint64_t)(p[0])) | ((uint64_t)(p[1]) << 8) |
((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56);
return ((uint64_t) (p[0])) | ((uint64_t) (p[1]) << 8) | ((uint64_t) (p[2]) << 16) |
((uint64_t) (p[3]) << 24) | ((uint64_t) (p[4]) << 32) | ((uint64_t) (p[5]) << 40) |
((uint64_t) (p[6]) << 48) | ((uint64_t) (p[7]) << 56);
}
void
@ -116,7 +119,6 @@ xfprintf(FILE *fp, const char *format, ...)
va_end(va);
if (fwrite(out, (size_t) len, 1U, fp) != 1U) {
sodium_free(out);
va_end(va);
exit_err("fwrite()");
}
sodium_free(out);
@ -127,8 +129,8 @@ xfprintf(FILE *fp, const char *format, ...)
int
xfput_b64(FILE *fp, const unsigned char *bin, size_t bin_len)
{
const size_t b64_maxlen = (bin_len + 2) * 4 / 3 + 1;
char *b64;
const size_t b64_maxlen = (bin_len + 2) * 4 / 3 + 1;
char *b64;
b64 = xsodium_malloc(b64_maxlen);
if (bin_to_b64(b64, bin, b64_maxlen, bin_len) == NULL) {
@ -153,16 +155,21 @@ xfclose(FILE *fp)
return 0;
}
void
int
trim(char *str)
{
size_t i = strlen(str);
int t = 0;
while (i-- > (size_t) 0U) {
if (str[i] == '\n' || str[i] == '\r') {
if (str[i] == '\n') {
str[i] = 0;
t = 1;
} else if (str[i] == '\r') {
str[i] = 0;
}
}
return t;
}
const char *
@ -182,8 +189,7 @@ fopen_create_useronly(const char *file)
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
int fd;
if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY,
(mode_t) 0600)) == -1) {
if ((fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, (mode_t) 0600)) == -1) {
return NULL;
}
return fdopen(fd, "w");
@ -199,7 +205,7 @@ basedir_create_useronly(const char *file)
char *dir;
int ret = -1;
dir = xstrdup(file);
dir = xstrdup(file);
basename = file_basename(dir);
if (basename == dir) {
free(dir);
@ -220,9 +226,10 @@ basedir_create_useronly(const char *file)
return ret;
}
char *get_home_dir(void)
char *
get_home_dir(void)
{
char *dir;
char *dir;
#ifdef _WIN32
const char *hd;
const char *hp;
@ -238,8 +245,7 @@ char *get_home_dir(void)
if ((dir = getenv("USERPROFILE")) != NULL) {
return xstrdup(dir);
}
if ((hd = getenv("HOMEDRIVE")) != NULL &&
(hp = getenv("HOMEPATH")) != NULL) {
if ((hd = getenv("HOMEDRIVE")) != NULL && (hp = getenv("HOMEPATH")) != NULL) {
if (asprintf(&dir, "%s%s", hd, hp) < 0) {
exit_err("asprintf()");
}

View file

@ -2,16 +2,16 @@
#ifndef HELPERS_H
#define HELPERS_H 1
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#if !defined(__GNUC__) && !defined(__attribute__)
# define __attribute__(X)
# define __attribute__(X)
#endif
#ifdef _WIN32
# define DIR_SEP '\\'
# define DIR_SEP '\\'
#else
# define DIR_SEP '/'
# define DIR_SEP '/'
#endif
uint64_t le64_load(const unsigned char *p);
@ -22,11 +22,11 @@ void exit_err(const char *msg) __attribute__((noreturn));
void exit_msg(const char *msg) __attribute__((noreturn));
void * xmalloc(size_t size);
void *xmalloc(size_t size);
char * xstrdup(const char *str);
char *xstrdup(const char *str);
void * xsodium_malloc(size_t size);
void *xsodium_malloc(size_t size);
void xor_buf(unsigned char *dst, const unsigned char *src, size_t len);
@ -36,14 +36,14 @@ int xfprintf(FILE *fp, const char *format, ...) __attribute__((format(printf, 2,
int xfclose(FILE *fp);
void trim(char *str);
int trim(char *str);
const char * file_basename(const char *file);
const char *file_basename(const char *file);
FILE * fopen_create_useronly(const char *file);
FILE *fopen_create_useronly(const char *file);
int basedir_create_useronly(const char *file);
char * get_home_dir(void);
char *get_home_dir(void);
#endif

120
src/libzodium/libzodium.zig Normal file
View file

@ -0,0 +1,120 @@
const std = @import("std");
const crypto = std.crypto;
const mem = std.mem;
const Ed25519 = crypto.sign.Ed25519;
export fn sodium_init() callconv(.C) c_int {
return 0;
}
export fn sodium_memzero(pnt: [*c]u8, len: usize) callconv(.C) void {
crypto.utils.secureZero(u8, pnt[0..len]);
}
export fn randombytes_buf(pnt: [*c]u8, len: usize) callconv(.C) void {
crypto.random.bytes(pnt[0..len]);
}
export fn sodium_malloc(len: usize) callconv(.C) ?*anyopaque {
return std.c.malloc(len);
}
export fn sodium_free(pnt: ?*anyopaque) callconv(.C) void {
return std.c.free(pnt);
}
export fn crypto_pwhash_scryptsalsa208sha256(
out: [*c]u8,
outlen: c_ulonglong,
passwd: [*c]const u8,
passwdlen: c_ulonglong,
salt: [*c]const u8,
opslimit: c_ulonglong,
memlimit: usize,
) callconv(.C) c_int {
crypto.pwhash.scrypt.kdf(
std.heap.c_allocator,
out[0..@intCast(outlen)],
passwd[0..@intCast(passwdlen)],
salt[0..32],
crypto.pwhash.scrypt.Params.fromLimits(opslimit, memlimit),
) catch return -1;
return 0;
}
const crypto_generichash_state = crypto.hash.blake2.Blake2b512;
export fn crypto_generichash_init(
state: *crypto_generichash_state,
_: [*c]const u8,
_: usize,
outlen: usize,
) c_int {
state.* = crypto.hash.blake2.Blake2b512.init(.{ .expected_out_bits = outlen * 8 });
return 0;
}
export fn crypto_generichash_update(
state: *crypto_generichash_state,
in: [*c]const u8,
inlen: c_ulonglong,
) c_int {
state.*.update(in[0..@intCast(inlen)]);
return 0;
}
export fn crypto_generichash_final(
state: *crypto_generichash_state,
out: [*c]u8,
outlen: usize,
) c_int {
var h: [64]u8 = undefined;
state.*.final(&h);
@memcpy(out[0..outlen], h[0..outlen]);
return 0;
}
export fn crypto_sign_keypair(pk: [*c]u8, sk: [*c]u8) callconv(.C) c_int {
const kp = if (std.meta.hasFn(Ed25519.KeyPair, "generate")) Ed25519.KeyPair.generate() else (Ed25519.KeyPair.create(null) catch return -1);
pk[0..32].* = kp.public_key.toBytes();
sk[0..64].* = kp.secret_key.toBytes();
return 0;
}
export fn crypto_sign_detached(
sig_bytes: [*c]u8,
_: [*c]c_ulonglong,
m: [*c]const u8,
mlen: c_ulonglong,
sk_bytes: [*c]const u8,
) callconv(.C) c_int {
const sk = Ed25519.SecretKey.fromBytes(sk_bytes[0..64].*) catch return -1;
const kp = Ed25519.KeyPair.fromSecretKey(sk) catch return -1;
var noise: [Ed25519.noise_length]u8 = undefined;
crypto.random.bytes(&noise);
const s = kp.sign(m[0..@intCast(mlen)], noise) catch return -1;
sig_bytes[0..64].* = s.toBytes();
return 0;
}
export fn crypto_sign_verify_detached(
sig_bytes: [*c]const u8,
m: [*c]const u8,
mlen: c_ulonglong,
pk_bytes: [*c]const u8,
) callconv(.C) c_int {
const pk = Ed25519.PublicKey.fromBytes(pk_bytes[0..32].*) catch return -1;
const sig = Ed25519.Signature.fromBytes(sig_bytes[0..64].*);
sig.verify(m[0..@intCast(mlen)], pk) catch return 1;
return 0;
}
export fn sodium_bin2hex(
hex: [*c]u8,
hex_maxlen: usize,
bin: [*c]const u8,
bin_len: usize,
) callconv(.C) [*c]u8 {
_ = std.fmt.bufPrint(hex[0..hex_maxlen], "{s}", .{std.fmt.fmtSliceHexLower(bin[0..bin_len])}) catch return null;
return hex;
}

62
src/libzodium/sodium.h Normal file
View file

@ -0,0 +1,62 @@
#pragma once
#include <stddef.h>
int sodium_init(void) __attribute__((warn_unused_result));
;
void sodium_memzero(void* const pnt, const size_t len);
void randombytes_buf(void* const buf, const size_t size) __attribute__((nonnull));
void* sodium_malloc(const size_t size) __attribute__((malloc));
void sodium_free(void* ptr);
#define crypto_pwhash_scryptsalsa208sha256_SALTBYTES 32U
#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_MIN 32768U
#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_MIN 16777216U
#define crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE 33554432U
#define crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE 1073741824U
int crypto_pwhash_scryptsalsa208sha256(unsigned char* const out,
unsigned long long outlen,
const char* const passwd,
unsigned long long passwdlen,
const unsigned char* const salt,
unsigned long long opslimit,
size_t memlimit) __attribute__((warn_unused_result))
__attribute__((nonnull));
typedef struct crypto_generichash_state {
unsigned char opaque[512];
} crypto_generichash_state;
#define crypto_generichash_BYTES_MAX 64U
#define crypto_generichash_BYTES 32U
int crypto_generichash_init(crypto_generichash_state* state, const unsigned char* key,
const size_t keylen, const size_t outlen) __attribute__((nonnull(1)));
int crypto_generichash_update(crypto_generichash_state* state,
const unsigned char* in,
unsigned long long inlen) __attribute__((nonnull(1)));
int crypto_generichash_final(crypto_generichash_state* state, unsigned char* out,
const size_t outlen) __attribute__((nonnull));
#define crypto_sign_SECRETKEYBYTES 64
#define crypto_sign_PUBLICKEYBYTES 32
#define crypto_sign_BYTES 64
int crypto_sign_keypair(unsigned char* pk, unsigned char* sk) __attribute__((nonnull));
int crypto_sign_detached(unsigned char* sig, unsigned long long* siglen_p, const unsigned char* m,
unsigned long long mlen, const unsigned char* sk)
__attribute__((nonnull(1, 5)));
int crypto_sign_verify_detached(const unsigned char* sig,
const unsigned char* m,
unsigned long long mlen,
const unsigned char* pk) __attribute__((warn_unused_result))
__attribute__((nonnull(1, 4)));

View file

@ -1,18 +1,20 @@
<!---
This man page can be generated using ronn - http://rtomayko.github.com/ronn/
This man page can be generated using ronn - https://rtomayko.github.io/ronn/
-->
minisign(1) -- A dead simple tool to sign files and verify signatures.
======================================================================
# minisign(1) -- A dead simple tool to sign files and verify signatures.
## SYNOPSIS
`minisign` -G [-p pubkey] [-s seckey]
`minisign` -G [-p pubkey_file] [-s seckey_file] [-W]
`minisign` -S [-H] [-x sigfile] [-s seckey] [-c untrusted_comment] [-t trusted_comment] -m file [file ...]
`minisign` -R [-s seckey_file] [-p pubkey_file]
`minisign` -V [-x sigfile] [-p pubkeyfile | -P pubkey] [-o] [-q] -m file
`minisign` -C [-s seckey_file] [-W]
`minisign` -R -s seckey -p pubkeyfile
`minisign` -S [-H] [-x sig_file] [-s seckey_file] [-c untrusted_comment] [-t trusted_comment] -m file [file ...]
`minisign` -V [-x sig_file] [-p pubkey_file | -P pubkey] [-o] [-q] -m file
## DESCRIPTION
@ -24,41 +26,46 @@ It is portable, lightweight, and uses the highly secure [Ed25519](http://ed25519
These options control the actions of `minisign`.
* `-G`:
Generate a new key pair
* `-S`:
Sign files
* `-V`:
Verify that a signature is valid for a given file
* `-m <file>`:
File to sign/verify
* `-o`:
Combined with -V, output the file content after verification
* `-H`:
Combined with -S, pre-hash in order to sign large files
* `-p <pubkeyfile>`:
Public key file (default: ./minisign.pub)
* `-P <pubkey>`:
Public key, as a base64 string
* `-s <seckey>`:
Secret key file (default: ~/.minisign/minisign.key)
* `-x <sigfile>`:
Signature file (default: &lt;file&gt;.minisig)
* `-c <comment>`:
Add a one-line untrusted comment
* `-t <comment>`:
Add a one-line trusted comment
* `-q`:
Quiet mode, suppress output
* `-Q`:
Pretty quiet mode, only print the trusted comment
* `-R`:
Recreate a public key file from a secret key file
* `-f`:
Force. Combined with -G, overwrite a previous key pair
* `-v`:
Display version number
- `-G`:
Generate a new key pair
- `-C`:
Change/remove the password of a secret key
- `-R`:
Recreate a public key file from a secret key file
- `-S`:
Sign files
- `-V`:
Verify that a signature is valid for a given file
- `-H`:
Requires the input to be prehashed
- `-l`:
Sign using the legacy format
- `-m <file>`:
File to sign/verify
- `-o`:
Combined with -V, output the file content after verification
- `-p <pubkey_file>`:
Public key file (default: ./minisign.pub)
- `-P <pubkey>`:
Public key, as a base64 string
- `-s <seckey_file>`:
Secret key file (default: ~/.minisign/minisign.key)
- `-W`:
Do not encrypt/decrypt the secret key with a password
- `-x <sig_file>`:
Signature file (default: &lt;file&gt;.minisig)
- `-c <comment>`:
Add a one-line untrusted comment
- `-t <comment>`:
Add a one-line trusted comment
- `-q`:
Quiet mode, suppress output
- `-Q`:
Pretty quiet mode, only print the trusted comment
- `-f`:
Force. Combined with -G, overwrite a previous key pair
- `-v`:
Display version number
## EXAMPLES
@ -71,7 +78,7 @@ The public key is printed and put into the `minisign.pub` file. The secret key i
Signing files
$ `minisign` -Sm myfile.txt
$ `minisign` -Sm myfile.txt myfile2.txt *.c
$ `minisign` -Sm myfile.txt myfile2.txt \*.c
Or to include a comment in the signature, that will be verified and displayed when verifying the file:
@ -81,7 +88,7 @@ The secret key is loaded from `${MINISIGN_CONFIG_DIR}/minisign.key`, `~/.minisig
Verifying a file
$ `minisign` -Vm myfile.txt -p &lt;pubkey&gt;
$ `minisign` -Vm myfile.txt -P &lt;pubkey&gt;
or
@ -91,39 +98,15 @@ This requires the signature `myfile.txt.minisig` to be present in the same direc
The public key can either reside in a file (`./minisign.pub` by default) or be directly specified on the command line.
## Notes
## NOTES
**Trusted comments**
Signature files include an untrusted comment line that can be freely modified even after the signature is created.
Signature files include an untrusted comment line that can be freely modified, even after signature creation.
They also include a second comment line that cannot be modified without the secret key.
They also include a second comment line, that cannot be modified without the secret key.
Trusted comments can be used to add instructions or application-specific metadata such as the intended file name, timestamps, resource identifiers, or version numbers to prevent downgrade attacks.
Trusted comments can be used to add instructions or application-specific metadata (intended file name, timestamps, resource identifiers, version numbers to prevent downgrade attacks).
**Compatibility with OpenBSD signify**
Signatures written by `minisign` can be verified using OpenBSD's `signify` tool: public key files and signature files are compatible.
However, `minisign` uses a slightly different format to store secret keys.
`Minisign` signatures include trusted comments in addition to untrusted comments. Trusted comments are signed, thus verified, before being displayed.
This adds two lines to the signature files, that signify silently ignores.
**Pre-hashing**
By default, signing and verification require as much memory as the size of the file.
Since `Minisign 0.6`, huge files can be signed and verified with very low memory requirements, by pre-hashing the content.
The -H command-line switch, in combination with -S, generates a pre-hashed signature (HashEdDSA):
$ `minisign` -SHm myfile.txt
Verification of such a signature doesn't require any specific switch: the appropriate algorithm will automatically be detected.
Signatures generated that way are not compatible with OpenBSD's `signify` tool and are not compatible with `Minisign` versions prior to 0.6.
OpenBSD's `signify(1)` is conceptually similar to Minisign. Minisign creates signatures that can be verified by `signify`; however, signatures created by `signify` cannot be verified with Minisign because Minisign expects a trusted comment section to be present. Trusted comments are crucial for describing what has been signed, in addition to merely confirming that a signature exists.
## AUTHOR

File diff suppressed because it is too large Load diff

View file

@ -2,24 +2,25 @@
#ifndef MINISIGN_H
#define MINISIGN_H 1
#define COMMENTMAXBYTES 1024
#define KEYNUMBYTES 8
#define PASSWORDMAXBYTES 1024
#define TRUSTEDCOMMENTMAXBYTES 8192
#define SIGALG "Ed"
#define SIGALG_HASHED "ED"
#define KDFALG "Sc"
#define CHKALG "B2"
#define COMMENT_PREFIX "untrusted comment: "
#define DEFAULT_COMMENT "signature from minisign secret key"
#define SECRETKEY_DEFAULT_COMMENT "minisign encrypted secret key"
#define TRUSTED_COMMENT_PREFIX "trusted comment: "
#define SIG_DEFAULT_CONFIG_DIR ".minisign"
#define COMMENTMAXBYTES 1024
#define KEYNUMBYTES 8
#define PASSWORDMAXBYTES 1024
#define TRUSTEDCOMMENTMAXBYTES 8192
#define SIGALG "Ed"
#define SIGALG_HASHED "ED"
#define KDFALG "Sc"
#define KDFNONE "\0\0"
#define CHKALG "B2"
#define COMMENT_PREFIX "untrusted comment: "
#define DEFAULT_COMMENT "signature from minisign secret key"
#define SECRETKEY_DEFAULT_COMMENT "minisign encrypted secret key"
#define TRUSTED_COMMENT_PREFIX "trusted comment: "
#define SIG_DEFAULT_CONFIG_DIR ".minisign"
#define SIG_DEFAULT_CONFIG_DIR_ENV_VAR "MINISIGN_CONFIG_DIR"
#define SIG_DEFAULT_PKFILE "minisign.pub"
#define SIG_DEFAULT_SKFILE "minisign.key"
#define SIG_SUFFIX ".minisig"
#define VERSION_STRING "minisign 0.9"
#define SIG_DEFAULT_PKFILE "minisign.pub"
#define SIG_DEFAULT_SKFILE "minisign.key"
#define SIG_SUFFIX ".minisig"
#define VERSION_STRING "minisign 0.12"
typedef struct KeynumSK_ {
unsigned char keynum[KEYNUMBYTES];
@ -39,12 +40,12 @@ typedef struct SeckeyStruct_ {
unsigned char kdf_salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
unsigned char kdf_opslimit_le[8];
unsigned char kdf_memlimit_le[8];
KeynumSK keynum_sk;
KeynumSK keynum_sk;
} SeckeyStruct;
typedef struct PubkeyStruct_ {
unsigned char sig_alg[2];
KeynumPK keynum_pk;
KeynumPK keynum_pk;
} PubkeyStruct;
typedef struct SigStruct_ {
@ -58,7 +59,8 @@ typedef enum Action_ {
ACTION_GENERATE,
ACTION_SIGN,
ACTION_VERIFY,
ACTION_RECREATE_PK
ACTION_RECREATE_PK,
ACTION_UPDATE_PASSWORD
} Action;
#endif