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 Makefile
cmake_install.cmake cmake_install.cmake
minisign 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) 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_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_VERSION_MAJOR "0") 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_PACKAGE_VERSION_PATCH "0")
set( set(
CPACK_SOURCE_PACKAGE_FILE_NAME 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 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 ./ ./ 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 ||: RUN upx --lzma build/minisign ||:
FROM scratch FROM scratch

View file

@ -1,7 +1,7 @@
ISC LICENSE. ISC LICENSE.
/* /*
* Copyright (c) 2015-2020 * Copyright (c) 2015-2025
* Frank Denis <j at pureftpd dot org> * Frank Denis <j at pureftpd dot org>
* *
* Permission to use, copy, modify, and/or distribute this software for any * 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. Minisign is a dead simple tool to sign files and verify signatures.
@ -12,14 +12,39 @@ public key:
RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3 RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3
Compilation / installation ## Compilation / installation
--------------------------
## Building with Zig
Dependencies: Dependencies:
* [libsodium](https://libsodium.org/) - [libsodium](https://libsodium.org/) (_optional_)
* cmake - [zig](https://ziglang.org)
* pkg-config
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: Compilation:
@ -37,6 +62,8 @@ or:
$ cmake -D BUILD_STATIC_EXECUTABLES=1 .. $ cmake -D BUILD_STATIC_EXECUTABLES=1 ..
## Pre-built packages
Minisign is also available in Homebrew: Minisign is also available in Homebrew:
$ brew install minisign $ brew install minisign
@ -49,38 +76,57 @@ Minisign is also available in chocolatey on Windows:
$ choco install minisign $ 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: Minisign is also available with docker:
$ docker run -i --rm jedisct1/minisign $ 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 $ docker run -v .:/minisign -e HOME=/minisign -w /minisign \
nice set of workflows and scripts for macOS to verify and sign files -it --rm jedisct1/minisign \
with minisign. -Vm file_to_verify -p minisign.pub
* [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.
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 This implementation uses deterministic signatures, unless libsodium
was compiled with the `ED25519_NONDETERMINISTIC` macro defined. This 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 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "MINISIGN" "1" "June 2020" "" "" .TH "MINISIGN" "1" "March 2025" "" ""
. .
.SH "NAME" .SH "NAME"
\fBminisign\fR \- A dead simple tool to sign files and verify signatures\. \fBminisign\fR \- A dead simple tool to sign files and verify signatures\.
. .
.SH "SYNOPSIS" .SH "SYNOPSIS"
\fBminisign\fR \-G [\-p pubkey] [\-s seckey] \fBminisign\fR \-G [\-p pubkey_file] [\-s seckey_file] [\-W]
. .
.P .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 .P
\fBminisign\fR \-V [\-x sigfile] [\-p pubkeyfile | \-P pubkey] [\-o] [\-q] \-m file \fBminisign\fR \-C [\-s seckey_file] [\-W]
. .
.P .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" .SH "DESCRIPTION"
\fBMinisign\fR is a dead simple tool to sign files and verify signatures\. \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 Generate a new key pair
. .
.TP .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 \fB\-S\fR
Sign files Sign files
. .
@ -40,6 +51,14 @@ Sign files
Verify that a signature is valid for a given file Verify that a signature is valid for a given file
. .
.TP .TP
\fB\-H\fR
Requires the input to be prehashed
.
.TP
\fB\-l\fR
Sign using the legacy format
.
.TP
\fB\-m <file>\fR \fB\-m <file>\fR
File to sign/verify File to sign/verify
. .
@ -48,11 +67,7 @@ File to sign/verify
Combined with \-V, output the file content after verification Combined with \-V, output the file content after verification
. .
.TP .TP
\fB\-H\fR \fB\-p <pubkey_file>\fR
Combined with \-S, pre\-hash in order to sign large files
.
.TP
\fB\-p <pubkeyfile>\fR
Public key file (default: \./minisign\.pub) Public key file (default: \./minisign\.pub)
. .
.TP .TP
@ -60,11 +75,15 @@ Public key file (default: \./minisign\.pub)
Public key, as a base64 string Public key, as a base64 string
. .
.TP .TP
\fB\-s <seckey>\fR \fB\-s <seckey_file>\fR
Secret key file (default: ~/\.minisign/minisign\.key) Secret key file (default: ~/\.minisign/minisign\.key)
. .
.TP .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) Signature file (default: <file>\.minisig)
. .
.TP .TP
@ -84,10 +103,6 @@ Quiet mode, suppress output
Pretty quiet mode, only print the trusted comment Pretty quiet mode, only print the trusted comment
. .
.TP .TP
\fB\-R\fR
Recreate a public key file from a secret key file
.
.TP
\fB\-f\fR \fB\-f\fR
Force\. Combined with \-G, overwrite a previous key pair 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 Verifying a file
. .
.P .P
$ \fBminisign\fR \-Vm myfile\.txt \-p <pubkey> $ \fBminisign\fR \-Vm myfile\.txt \-P <pubkey>
. .
.P .P
or or
@ -137,53 +152,17 @@ This requires the signature \fBmyfile\.txt\.minisig\fR to be present in the same
.P .P
The public key can either reside in a file (\fB\./minisign\.pub\fR by default) or be directly specified on the command line\. 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" .SH "NOTES"
\fBTrusted comments\fR Signature files include an untrusted comment line that can be freely modified even after the signature is created\.
. .
.P .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 .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 .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)\. 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\.
.
.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\.
. .
.SH "AUTHOR" .SH "AUTHOR"
Frank Denis (github [at] pureftpd [dot] org) Frank Denis (github [at] pureftpd [dot] org)

View file

@ -5,44 +5,70 @@
#include "base64.h" #include "base64.h"
unsigned char * unsigned char *
b64_to_bin(unsigned char * const bin, const char *b64, b64_to_bin(unsigned char *const bin, const char *b64, size_t bin_maxlen, size_t b64_len,
size_t bin_maxlen, size_t b64_len, size_t * const bin_len_p) size_t *const bin_len_p)
{ {
#define REV64_EOT 128U #define REV64_EOT 128U
#define REV64_NONE 64U #define REV64_NONE 64U
#define REV64_PAD '=' #define REV64_PAD '='
static const unsigned char rev64chars[256] = { 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, REV64_NONE, REV64_NONE, 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, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
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, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE,
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, 62U, REV64_NONE, REV64_NONE, REV64_NONE, 63U, 52U,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, 53U, 54U, 55U, 56U, 57U, 58U, 59U,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, 60U, 61U, REV64_NONE, REV64_NONE, REV64_NONE, REV64_EOT, REV64_NONE,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, 0U, 1U, 2U, 3U, 4U,
REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE, REV64_NONE 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; const unsigned char *b64_u = (const unsigned char *) b64;
unsigned char *bin_w = bin; unsigned char *bin_w = bin;
unsigned char mask = 0U; unsigned char mask = 0U;
unsigned char t0 = 0, t1 = 0 , t2 = 0, t3 = 0; unsigned char t0 = 0, t1 = 0, t2 = 0, t3 = 0;
uint32_t t = 0; uint32_t t = 0;
size_t i; size_t i;
if (b64_len % 4U != 0U || (i = b64_len / 4U) <= 0U || bin_maxlen < i * 3U - if (b64_len % 4U != 0U || (i = b64_len / 4U) <= 0U ||
(b64_u[b64_len - 1U] == REV64_PAD) - (b64_u[b64_len - 2U] == REV64_PAD)) { bin_maxlen <
i * 3U - (b64_u[b64_len - 1U] == REV64_PAD) - (b64_u[b64_len - 2U] == REV64_PAD)) {
return NULL; return NULL;
} }
while (i-- > 0U) { while (i-- > 0U) {
t0 = rev64chars[*b64_u++]; t0 = rev64chars[*b64_u++];
t1 = rev64chars[*b64_u++]; t1 = rev64chars[*b64_u++];
t2 = rev64chars[*b64_u++]; t2 = rev64chars[*b64_u++];
t3 = rev64chars[*b64_u++]; t3 = rev64chars[*b64_u++];
t = t3 | ((uint32_t) t2 << 6) | ((uint32_t) t1 << 12) | t = t3 | ((uint32_t) t2 << 6) | ((uint32_t) t1 << 12) | ((uint32_t) t0 << 18);
((uint32_t) t0 << 18);
mask = t0 | t1 | t2 | t3; mask = t0 | t1 | t2 | t3;
if ((mask & (REV64_NONE | REV64_EOT)) != 0U) { if ((mask & (REV64_NONE | REV64_EOT)) != 0U) {
if ((mask & REV64_NONE) != 0U || i > 0U) { if ((mask & REV64_NONE) != 0U || i > 0U) {
@ -69,8 +95,8 @@ b64_to_bin(unsigned char * const bin, const char *b64,
return bin; return bin;
} }
char *bin_to_b64(char * const b64, const unsigned char *bin, char *
size_t b64_maxlen, size_t bin_len) bin_to_b64(char *const b64, const unsigned char *bin, size_t b64_maxlen, size_t bin_len)
{ {
#define B64_PAD '=' #define B64_PAD '='

View file

@ -4,12 +4,10 @@
#include <stddef.h> #include <stddef.h>
unsigned char *b64_to_bin(unsigned char * const bin, const char *b64, unsigned char *b64_to_bin(unsigned char *const bin, const char *b64, size_t bin_maxlen,
size_t bin_maxlen, size_t b64_len, size_t b64_len, size_t *const bin_len_p);
size_t * const bin_len_p);
char *bin_to_b64(char * const b64, const unsigned char *bin, char *bin_to_b64(char *const b64, const unsigned char *bin, size_t b64_maxlen, size_t bin_len);
size_t b64_maxlen, size_t bin_len);
#define B64_MAX_LEN_FROM_BIN_LEN(X) (((X) + 2) / 3 * 4 + 1) #define B64_MAX_LEN_FROM_BIN_LEN(X) (((X) + 2) / 3 * 4 + 1)
#define BIN_MAX_LEN_FROM_B64_LEN(X) ((X) / 4 * 3) #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__) #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
# include <sys/types.h> # include <sys/types.h>
#endif #endif
#include <assert.h> #include <assert.h>
@ -10,19 +10,19 @@
#include <string.h> #include <string.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
# include <fcntl.h> # include <fcntl.h>
# include <poll.h> # include <poll.h>
# include <termios.h> # include <termios.h>
# include <unistd.h> # include <unistd.h>
#elif defined(_WIN32) #elif defined(_WIN32)
# include <windows.h> # include <windows.h>
#endif #endif
#include "get_line.h" #include "get_line.h"
#include "helpers.h" #include "helpers.h"
#ifndef TCSAFLUSH #ifndef TCSAFLUSH
# define TCSAFLUSH 0 # define TCSAFLUSH 0
#endif #endif
#ifndef VERIFY_ONLY #ifndef VERIFY_ONLY
@ -33,7 +33,7 @@ disable_echo(void)
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) # if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
{ {
struct termios p; struct termios p;
@ -43,15 +43,15 @@ disable_echo(void)
p.c_lflag &= ~ECHO; p.c_lflag &= ~ECHO;
tcsetattr(0, TCSAFLUSH, &p); tcsetattr(0, TCSAFLUSH, &p);
} }
# elif defined(_WIN32) # elif defined(_WIN32)
{ {
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode = 0; DWORD mode = 0;
GetConsoleMode(handle, &mode); GetConsoleMode(handle, &mode);
SetConsoleMode(handle, mode & ~ENABLE_ECHO_INPUT); SetConsoleMode(handle, mode & ~ENABLE_ECHO_INPUT);
} }
# endif # endif
} }
static void static void
@ -60,7 +60,7 @@ enable_echo(void)
fflush(stdout); fflush(stdout);
fflush(stderr); fflush(stderr);
# if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) # if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__)
{ {
struct termios p; struct termios p;
@ -70,15 +70,15 @@ enable_echo(void)
p.c_lflag |= ECHO; p.c_lflag |= ECHO;
tcsetattr(0, TCSAFLUSH, &p); tcsetattr(0, TCSAFLUSH, &p);
} }
# elif defined(_WIN32) # elif defined(_WIN32)
{ {
HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode = 0; DWORD mode = 0;
GetConsoleMode(handle, &mode); GetConsoleMode(handle, &mode);
SetConsoleMode(handle, mode | ENABLE_ECHO_INPUT); SetConsoleMode(handle, mode | ENABLE_ECHO_INPUT);
} }
# endif # endif
} }
int int

View file

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

View file

@ -2,16 +2,16 @@
#ifndef HELPERS_H #ifndef HELPERS_H
#define HELPERS_H 1 #define HELPERS_H 1
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#if !defined(__GNUC__) && !defined(__attribute__) #if !defined(__GNUC__) && !defined(__attribute__)
# define __attribute__(X) # define __attribute__(X)
#endif #endif
#ifdef _WIN32 #ifdef _WIN32
# define DIR_SEP '\\' # define DIR_SEP '\\'
#else #else
# define DIR_SEP '/' # define DIR_SEP '/'
#endif #endif
uint64_t le64_load(const unsigned char *p); 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 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); 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); 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); int basedir_create_useronly(const char *file);
char * get_home_dir(void); char *get_home_dir(void);
#endif #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 ## 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 ## DESCRIPTION
@ -24,41 +26,46 @@ It is portable, lightweight, and uses the highly secure [Ed25519](http://ed25519
These options control the actions of `minisign`. These options control the actions of `minisign`.
* `-G`: - `-G`:
Generate a new key pair Generate a new key pair
* `-S`: - `-C`:
Sign files Change/remove the password of a secret key
* `-V`: - `-R`:
Verify that a signature is valid for a given file Recreate a public key file from a secret key file
* `-m <file>`: - `-S`:
File to sign/verify Sign files
* `-o`: - `-V`:
Combined with -V, output the file content after verification Verify that a signature is valid for a given file
* `-H`: - `-H`:
Combined with -S, pre-hash in order to sign large files Requires the input to be prehashed
* `-p <pubkeyfile>`: - `-l`:
Public key file (default: ./minisign.pub) Sign using the legacy format
* `-P <pubkey>`: - `-m <file>`:
Public key, as a base64 string File to sign/verify
* `-s <seckey>`: - `-o`:
Secret key file (default: ~/.minisign/minisign.key) Combined with -V, output the file content after verification
* `-x <sigfile>`: - `-p <pubkey_file>`:
Signature file (default: &lt;file&gt;.minisig) Public key file (default: ./minisign.pub)
* `-c <comment>`: - `-P <pubkey>`:
Add a one-line untrusted comment Public key, as a base64 string
* `-t <comment>`: - `-s <seckey_file>`:
Add a one-line trusted comment Secret key file (default: ~/.minisign/minisign.key)
* `-q`: - `-W`:
Quiet mode, suppress output Do not encrypt/decrypt the secret key with a password
* `-Q`: - `-x <sig_file>`:
Pretty quiet mode, only print the trusted comment Signature file (default: &lt;file&gt;.minisig)
* `-R`: - `-c <comment>`:
Recreate a public key file from a secret key file Add a one-line untrusted comment
* `-f`: - `-t <comment>`:
Force. Combined with -G, overwrite a previous key pair Add a one-line trusted comment
* `-v`: - `-q`:
Display version number 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 ## EXAMPLES
@ -71,7 +78,7 @@ The public key is printed and put into the `minisign.pub` file. The secret key i
Signing files Signing files
$ `minisign` -Sm myfile.txt $ `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: 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 Verifying a file
$ `minisign` -Vm myfile.txt -p &lt;pubkey&gt; $ `minisign` -Vm myfile.txt -P &lt;pubkey&gt;
or 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. 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). 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.
**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.
## AUTHOR ## AUTHOR

File diff suppressed because it is too large Load diff

View file

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