{"thread":{"id":"55646","subject":"[RFC PATCH v1 0/1] Universal cryptographic signing","startedAt":"2021-05-08T06:18:28Z","lastAt":"2021-05-09T00:17:08Z","messageCount":4,"participants":["Dave Huseby","Bagas Sanjaya","brian m. carlson"],"isPatch":true,"patchVersion":1,"patchTotal":1},"messages":[{"id":"423916","messageId":"cover.1620454449.git.dwh@linuxprogrammer.org","threadId":"55646","inReplyTo":null,"subject":"[RFC PATCH v1 0/1] Universal cryptographic signing","fromName":"Dave Huseby","fromEmail":"dwh@linuxprogrammer.org","sentAt":"2021-05-08T06:18:22Z","receivedAt":"2021-05-08T06:18:28Z","isPatch":true,"sender":{"key":"dwh@linuxprogrammer.org","avatar":null},"body":"This RFC patchset is the beginning of a project generously sponsored by\nGoogle and the Linux Foundation to modify Git to have universal\ncryptographic signing capabilities. Curently Git only supports gpg and\ngpgsm and the primary goal is to create the ability to use any\nsigning/verification tool to sign Git commits, tags, mergetags, and\npushes with a specific emphasis on supporting OpenSSH.\n\nThe goals of this project are:\n\n- maintain full backwards compatibility without intervention. if it\n  works today, it will work after these patches land without any\n  modification to configs or support scripts.\n- remove all tool-specific code and replace it with a protocol driver\n  for using a standard protocol to talk to external signing and\n  verification tools.\n- normalize all of the command line switches so that they are the same\n  for all tools that support signing and they are no longer tool\n  specific (e.g. --sign instead of --gpgsign).\n- add a new sign.* configuration structure for specifying tool specific\n  configuration options (e.g. sign.openpgp.program) and deprecate all of\n  the signing related config options that are no longer needed (e.g.\n  user.signingKey).\n- make Git completely agnostic to the details of any signing regime by\n  storing signature data and options verbatim inside of signed objects\n  that it later passes to the associated verification tool.\n- add new tests needed to cover the new functionality while keeping all\n  of the old tests passing to verify backwards compatibility.\n\nThe proposed protocol for talking to signing/verification tools is a\npkt-line based protocol inspired by the Assuan protocol used by GPG for\nIPC between its component executables. The full write-up on the proposed\nprotocol is here:\n\nhttps://github.com/TrustFrame/git-cryptography-protocol/blob/main/Git%20Cryptography%20Protocol.md\n\nLike I said, this patchset is just the start of the project and all I\nhave done here is gone through all of the existing documentation and\nupdated it to reflect the normalized command line and config options as\nwell as documented the new sign.* config options and the proposed\nsignature format.\n\nI am especially looking for feedback on the proposed protocol, signature\nformat and config structure. I have plans to follow up this project with\nanother project to add support for config directories (e.g.\n.gitconfig.d) so that package maintainers will have an easier time of\nadding sign.* config values for arbitrary signing tools.\n\nAs of right now, I have only grok'ed the handling of signed objects and\nI have ignored signed pushes. I will be updating this patchset with\nchanges to the documentation for supporting universal signed pushes.\n\nThere's some sticky details around the transition to SHA256 that I think\nI have worked out well enough that it won't get in the way. That is\ndocumented in the hash-function-transition.txt file.\n\nI know there is a lot here, this project cuts deep and will require tons\nof test driven development to avoid killing the patient during surgery.\nI look forward to the many long conversations on details ;)\n\nCheers!\n\nDave Huseby (1):\n  Modifies documentation for universal cryptographic signing\n\n Documentation/config.txt                      |   2 +\n Documentation/config/commit.txt               |  23 +-\n Documentation/config/gpg.txt                  |  36 +--\n Documentation/config/push.txt                 |  18 +-\n Documentation/config/sign.txt                 |  72 ++++++\n Documentation/config/tag.txt                  |  27 +-\n Documentation/config/user.txt                 |  12 +-\n Documentation/git-am.txt                      |  43 +++-\n Documentation/git-cherry-pick.txt             |  43 +++-\n Documentation/git-commit-tree.txt             |  44 +++-\n Documentation/git-commit.txt                  |  43 +++-\n Documentation/git-fast-import.txt             |   2 +-\n Documentation/git-for-each-ref.txt            |   2 +-\n Documentation/git-mktag.txt                   |  32 ++-\n Documentation/git-rebase.txt                  |  44 +++-\n Documentation/git-revert.txt                  |  44 +++-\n Documentation/git-tag.txt                     | 102 +++++---\n Documentation/git-verify-commit.txt           |   8 +-\n Documentation/git-verify-tag.txt              |   8 +-\n Documentation/merge-options.txt               |  40 ++-\n Documentation/pretty-formats.txt              |   2 +-\n Documentation/pretty-options.txt              |   2 +-\n .../technical/hash-function-transition.txt    |  31 ++-\n .../technical/signature-format-v2.txt         | 232 ++++++++++++++++++\n Documentation/user-manual.txt                 |  40 +--\n 25 files changed, 747 insertions(+), 205 deletions(-)\n create mode 100644 Documentation/config/sign.txt\n create mode 100644 Documentation/technical/signature-format-v2.txt\n\n-- \n2.20.1\n\n"},{"id":"423917","messageId":"c454bcc4c3c5de1a17c63461c6091689098c75b9.1620454449.git.dwh@linuxprogrammer.org","threadId":"55646","inReplyTo":"cover.1620454449.git.dwh@linuxprogrammer.org","subject":"[RFC PATCH v1 1/1] Modifies documentation for universal cryptographic signing","fromName":"Dave Huseby","fromEmail":"dwh@linuxprogrammer.org","sentAt":"2021-05-08T06:18:23Z","receivedAt":"2021-05-08T06:18:30Z","isPatch":true,"sender":{"key":"dwh@linuxprogrammer.org","avatar":null},"body":"Signed-off-by: Dave Huseby <dwh@linuxprogrammer.org>\n---\n Documentation/config.txt                      |   2 +\n Documentation/config/commit.txt               |  23 +-\n Documentation/config/gpg.txt                  |  36 +--\n Documentation/config/push.txt                 |  18 +-\n Documentation/config/sign.txt                 |  72 ++++++\n Documentation/config/tag.txt                  |  27 +-\n Documentation/config/user.txt                 |  12 +-\n Documentation/git-am.txt                      |  43 +++-\n Documentation/git-cherry-pick.txt             |  43 +++-\n Documentation/git-commit-tree.txt             |  44 +++-\n Documentation/git-commit.txt                  |  43 +++-\n Documentation/git-fast-import.txt             |   2 +-\n Documentation/git-for-each-ref.txt            |   2 +-\n Documentation/git-mktag.txt                   |  32 ++-\n Documentation/git-rebase.txt                  |  44 +++-\n Documentation/git-revert.txt                  |  44 +++-\n Documentation/git-tag.txt                     | 102 +++++---\n Documentation/git-verify-commit.txt           |   8 +-\n Documentation/git-verify-tag.txt              |   8 +-\n Documentation/merge-options.txt               |  40 ++-\n Documentation/pretty-formats.txt              |   2 +-\n Documentation/pretty-options.txt              |   2 +-\n .../technical/hash-function-transition.txt    |  31 ++-\n .../technical/signature-format-v2.txt         | 232 ++++++++++++++++++\n Documentation/user-manual.txt                 |  40 +--\n 25 files changed, 747 insertions(+), 205 deletions(-)\n create mode 100644 Documentation/config/sign.txt\n create mode 100644 Documentation/technical/signature-format-v2.txt\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex bf82766a6a..71eb46117f 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -446,6 +446,8 @@ include::config/sequencer.txt[]\n \n include::config/showbranch.txt[]\n \n+include::config/sign.txt[]\n+\n include::config/splitindex.txt[]\n \n include::config/ssh.txt[]\ndiff --git a/Documentation/config/commit.txt b/Documentation/config/commit.txt\nindex 2c95573930..9004a2f3cb 100644\n--- a/Documentation/config/commit.txt\n+++ b/Documentation/config/commit.txt\n@@ -7,13 +7,24 @@ commit.cleanup::\n \thave to remove the help lines that begin with `#` in the commit log\n \ttemplate yourself, if you do this).\n \n-commit.gpgSign::\n+commit.gpgSign (deprecated)::\n+\tInterpreted as an alias for 'commit.sign'. Use of this implies\n+\t'commit.signType = openpgp' and the config values for \n+\t'sign.openpgp.*' are used if specified. If this is enabled and\n+\t'sign.openpgp.*' is not defined, backwards compatible defaults\n+\tare used that emulate the old behavior.\n \n-\tA boolean to specify whether all commits should be GPG signed.\n-\tUse of this option when doing operations such as rebase can\n-\tresult in a large number of commits being signed. It may be\n-\tconvenient to use an agent to avoid typing your GPG passphrase\n-\tseveral times.\n+commit.sign::\n+\tA boolean to specify whether all commits should be cryptographically\n+\tsigned. Use of this option when doing operations such as rebase can\n+\tresult in a large number of commits being signed.\n+\n+commit.signType::\n+\tA string value to specify the type of signature to use whenever\n+\t'--sign' is used or 'commit.sign' is enabled. If this is not defined\n+\tthe signature type defined by 'sign.default' is used. If neither\n+\tthis nor 'sign.default' are defined backwards compatible defaults\n+\tfor \"openpgp\" signatures are used.\n \n commit.status::\n \tA boolean to enable/disable inclusion of status information in the\ndiff --git a/Documentation/config/gpg.txt b/Documentation/config/gpg.txt\nindex d94025cb36..40629cb105 100644\n--- a/Documentation/config/gpg.txt\n+++ b/Documentation/config/gpg.txt\n@@ -1,32 +1,16 @@\n-gpg.program::\n-\tUse this custom program instead of \"`gpg`\" found on `$PATH` when\n-\tmaking or verifying a PGP signature. The program must support the\n-\tsame command-line interface as GPG, namely, to verify a detached\n-\tsignature, \"`gpg --verify $signature - <$file`\" is run, and the\n-\tprogram is expected to signal a good signature by exiting with\n-\tcode 0, and to generate an ASCII-armored detached signature, the\n-\tstandard input of \"`gpg -bsau $key`\" is fed with the contents to be\n-\tsigned, and the program is expected to send the result to its\n-\tstandard output.\n+gpg.program (deprecated)::\n+\tInterpreted as an alias for 'sign.openpgp.program'.\n \n-gpg.format::\n-\tSpecifies which key format to use when signing with `--gpg-sign`.\n-\tDefault is \"openpgp\" and another possible value is \"x509\".\n+gpg.format (deprecated)::\n+\tInterpreted as an alias for 'sign.default'. \n \n-gpg.<format>.program::\n-\tUse this to customize the program used for the signing format you\n-\tchose. (see `gpg.program` and `gpg.format`) `gpg.program` can still\n-\tbe used as a legacy synonym for `gpg.openpgp.program`. The default\n-\tvalue for `gpg.x509.program` is \"gpgsm\".\n+gpg.<format>.program (deprecated)::\n+\tInterpreted as an alias for 'sign.<format>.program' for format\n+\tvalues of \"openpgp\" and \"x509\".\n \n-gpg.minTrustLevel::\n-\tSpecifies a minimum trust level for signature verification.  If\n-\tthis option is unset, then signature verification for merge\n-\toperations require a key with at least `marginal` trust.  Other\n-\toperations that perform signature verification require a key\n-\twith at least `undefined` trust.  Setting this option overrides\n-\tthe required trust-level for all operations.  Supported values,\n-\tin increasing order of significance:\n+gpg.minTrustLevel (deprecated)::\n+\tInterpreted as an alias for 'sign.<format>.options.minTrustLevel' for\n+\tformat values of \"openpgp\" and \"x509\".\n +\n * `undefined`\n * `never`\ndiff --git a/Documentation/config/push.txt b/Documentation/config/push.txt\nindex 21b256e0a4..9a63bb273a 100644\n--- a/Documentation/config/push.txt\n+++ b/Documentation/config/push.txt\n@@ -61,15 +61,27 @@ push.followTags::\n \tmay override this configuration at time of push by specifying\n \t`--no-follow-tags`.\n \n-push.gpgSign::\n+push.gpgSign (deprecated)::\n+\tInterpreted as an alias for 'push.sign'. Use of this implies\n+\t'push.signType = openpgp' and the config values for\n+\t'sign.openpgp.*' are used if specified. If 'sign.openpgp.*' is not\n+\tdefined, backwards compatible defaults are used.\n+\n+push.sign::\n \tMay be set to a boolean value, or the string 'if-asked'. A true\n-\tvalue causes all pushes to be GPG signed, as if `--signed` is\n+\tvalue causes all pushes to be signed, as if `--sign` is\n \tpassed to linkgit:git-push[1]. The string 'if-asked' causes\n \tpushes to be signed if the server supports it, as if\n-\t`--signed=if-asked` is passed to 'git push'. A false value may\n+\t`--sign=if-asked` is passed to 'git push'. A false value may\n \toverride a value from a lower-priority config file. An explicit\n \tcommand-line flag always overrides this config option.\n \n+push.signType::\n+\tSpecifies the type of signature to use whenever '--sign' or\n+\t'push.sign' is enabled. If not defined, 'sign.default' determines\n+\tthe type of signature otherwise backwards compatible defaults are\n+\tused.\n+\n push.pushOption::\n \tWhen no `--push-option=<option>` argument is given from the\n \tcommand line, `git push` behaves as if each <value> of\ndiff --git a/Documentation/config/sign.txt b/Documentation/config/sign.txt\nnew file mode 100644\nindex 0000000000..a852da8803\n--- /dev/null\n+++ b/Documentation/config/sign.txt\n@@ -0,0 +1,72 @@\n+sign.default::\n+\tA string specifying the default signature type to use when signing\n+\tand the signature type is not specified with the '--sign-type'\n+\tcommand line switch. This specifies that the values from \n+\t'sign.<signType>.*' be used. If unspecified, the default is \"openpgp\"\n+\tfor backwards compatibility. The value can be any string but there\n+\tmust be a corresponding 'sign.<signType>.*' config block with at\n+\tleast 'sign.<signType>.program' defined.\n+\n+sign.openpgp.program::\n+\tDefines the program to use when signing or verifying with OpenPGP.\n+\tThe program must be found in the `$PATH` and if not defined, the\n+\tdefault is \"`gpg`\".\n+\n+sign.openpgp.sign::\n+\tDefines the program, found in the `$PATH` to use when signing with\n+\tOpenPGP. If specified, this overrides 'sign.openpgp.program' in\n+\tsigning operations.\n+\n+sign.openpgp.verify::\n+\tDefines the program, found in the `$PATH` to use when verifying an\n+\tOpenPGP signature. If specified, this overrides 'sign.openpgp.program'\n+\tin verification operations.\n+\n+sign.openpgp.options.*::\n+\tAny number of options that are passed verbatim to the signing tool\n+\twith 'OPTION' commands during a cryptographic signing event. If\n+\tnot defined, the default, backwards compatible options are:\n+\t'minTrustLevel = marginal', 'armored = true', and 'detached = true'\n+\tfor full backwards compatibility. This emulates the old\n+\t\"`gpg -bsau`\" way of creating an OpenPGP cryptographic signature.\n+\n+sign.x509.program::\n+\tDefines the program to use when signing or verifying using X.509\n+\tcertificates. The program must be found in the `$PATH` and if not\n+\tdefined, the default is \"`gpgsm`\".\n+\n+sign.x509.sign::\n+\tDefines the program, found in the `$PATH` to use when\n+\tcryptographically signing with X.509 certificates. If specified, this\n+\toverrides 'sign.x509.program' in signing operations.\n+\n+sign.x509.verify::\n+\tDefines the program, found in the `$PATH` to use when verifying an\n+\tX.509 cryptographic signature. If specified, this overrides\n+\t'sign.x509.program' in verification operations.\n+\n+sign.x509.options.*::\n+\tAny number of options that are passed verbatim to the signing tool\n+\twith 'OPTION' commands during a cryptographic signing event. If\n+\tnot defined, the default options are: 'minTrustLevel = marginal',\n+\t'armored = true', and 'detached = true' for full backwards\n+\tcompatibility. This emulates the old \"`gpgsm -bsau`\" way of creating\n+\tan X.509 cryptographic signature.\n+\n+sign.<signType>.program::\n+\tDefines the program, found in the `$PATH` to use when signing or\n+\tverifying signatures with the matching signature type.\n+\n+sign.<signType>.sign::\n+\tDefines the program, found in the `$PATH` to use when signing using\n+\tthe specified signature type. If specified, this overrides\n+\t'sign.<signType>.program' in signing operations.\n+\n+sign.<signType>.verify::\n+\tDefines the program, found in the `$PATH` to use when verifying\n+\tsignatures of type signature type. If specified, this overrides\n+\t'sign.<signType>.program' in verification operations.\n+\n+sign.<signType>.options.*::\n+\tAny number of options that are passed verbatim to the signing tool\n+\twith 'OPTION' commands during a signing event.\ndiff --git a/Documentation/config/tag.txt b/Documentation/config/tag.txt\nindex 5062a057ff..eff3286e59 100644\n--- a/Documentation/config/tag.txt\n+++ b/Documentation/config/tag.txt\n@@ -1,17 +1,24 @@\n tag.forceSignAnnotated::\n-\tA boolean to specify whether annotated tags created should be GPG signed.\n-\tIf `--annotate` is specified on the command line, it takes\n-\tprecedence over this option.\n+\tA boolean to specify whether annotated tags created should be\n+\tcryptographically signed. If `--annotate` is specified on the\n+\tcommand line, it takes precedence over this option.\n \n tag.sort::\n \tThis variable controls the sort ordering of tags when displayed by\n \tlinkgit:git-tag[1]. Without the \"--sort=<value>\" option provided, the\n \tvalue of this variable will be used as the default.\n \n-tag.gpgSign::\n-\tA boolean to specify whether all tags should be GPG signed.\n-\tUse of this option when running in an automated script can\n-\tresult in a large number of tags being signed. It is therefore\n-\tconvenient to use an agent to avoid typing your gpg passphrase\n-\tseveral times. Note that this option doesn't affect tag signing\n-\tbehavior enabled by \"-u <keyid>\" or \"--local-user=<keyid>\" options.\n+tag.gpgSign (deprecated)::\n+\tInterpreted as an alias for 'tag.sign'.\n+\n+tag.sign::\n+\tA boolean to specify whether all tags should be cryptographically\n+\tsigned. Use of this option when running in an automated script can\n+\tresult in a large number of tags being signed. Note that this option\n+\tdoesn't affect tag signing behavior enabled by \"-u <keyid>\" or\n+\t\"--local-user=<keyid>\" options.\n+\n+tag.sigType::\n+\tSpecifies the type of signature to use whenever '--sign' is used or\n+\t'tag.sign' is enabled. If undefined, 'sign.default' determines the\n+\ttype of signature to create.\ndiff --git a/Documentation/config/user.txt b/Documentation/config/user.txt\nindex 59aec7c3ae..a00209cd76 100644\n--- a/Documentation/config/user.txt\n+++ b/Documentation/config/user.txt\n@@ -30,9 +30,9 @@ user.useConfigOnly::\n \tmaking new commits in a newly cloned repository.\n \tDefaults to `false`.\n \n-user.signingKey::\n-\tIf linkgit:git-tag[1] or linkgit:git-commit[1] is not selecting the\n-\tkey you want it to automatically when creating a signed tag or\n-\tcommit, you can override the default selection with this variable.\n-\tThis option is passed unchanged to gpg's --local-user parameter,\n-\tso you may specify a key using any method that gpg supports.\n+user.signingKey (deprecated)::\n+\tFor backwards compatibility, if this is defined and if the signature\n+\ttype is specified as 'openpgp' or 'x509' using either '--sign-type' or\n+\t'sign.default', then this is interpreted as an alias for\n+\t'sign.openpgp.options.identifier' or 'sign.x509.options.identifier'\n+\trespectively.\ndiff --git a/Documentation/git-am.txt b/Documentation/git-am.txt\nindex decd8ae122..be94598c59 100644\n--- a/Documentation/git-am.txt\n+++ b/Documentation/git-am.txt\n@@ -14,7 +14,8 @@ SYNOPSIS\n \t [--ignore-date] [--ignore-space-change | --ignore-whitespace]\n \t [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]\n \t [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]\n-\t [--[no-]scissors] [-S[<keyid>]] [--patch-format=<format>]\n+\t [--[no-]scissors] [--sign] [(--sign-type <signType>)]\n+\t [(--sign-option <token>[=<value])...] [--patch-format=<format>]\n \t [(<mbox> | <Maildir>)...]\n 'git am' (--continue | --skip | --abort | --quit | --show-current-patch[=(diff|raw)])\n \n@@ -146,14 +147,38 @@ default.   You can use `--no-utf8` to override this.\n \tSkip the current patch.  This is only meaningful when\n \trestarting an aborted patch.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n---no-gpg-sign::\n-\tGPG-sign commits. The `keyid` argument is optional and\n-\tdefaults to the committer identity; if specified, it must be\n-\tstuck to the option without a space. `--no-gpg-sign` is useful to\n-\tcountermand both `commit.gpgSign` configuration variable, and\n-\tearlier `--gpg-sign`.\n+-S::\n+--sign::\n+--no-sign::\n+--gpg-sign[=<keyid>] (deprecated)::\n+--no-gpg-sign (deprecated)::\n+\tCryptographically sign commits. The `keyid` argument is deprecated\n+\tand the preferred way is to specify this as a configuration variable\n+\tas an option for the signing tool you use. For OpenPGP, you would\n+\tspecify this using 'sign.openpgp.options.identifier = <keyid>'. If\n+\tyou must pass the `keyid` on the command line, use\n+\t`--sign-option identifier=<keyid>`. For backwards compatibility, if\n+\tthe signature type is 'openpgp' or 'x509' and the `keyid` is\n+\tspecified, it is passed as if `--sign-option identifier=<keyid>` is\n+\talso specified. The `--no-sign` option is usefult to countermand both\n+\t'commit.sign' configuration variable and earlier `--sign` command line\n+\tswitches.\n+\n+--sign-type <signType>::\n+\tSpecifies the signature type to create when cryptographically signing\n+\tcommits. There must be a corresponding configuration block\n+\t'sign.<signType>.*' with at least 'sign.<signType>.program' specified.\n+\tFor backwards compatibility, 'openpgp' is assumed if the sign type\n+\tis not specified.\n+\n+--sign-option <token>[=<value>]::\n+\tSpecify an option to pass to the cryptographic signing tool using the\n+\tOPTION command in cryptographic signing protocol. Any number of\n+\toptions may be specified on the command line and they will override\n+\tany corresponding configuration variables with the same name. For\n+\texample, if the signature type is 'openpgp' and the configuration\n+\tvariable 'sign.openpgp.options.identifier' is set then\n+\t`--sign-option identifier=<keyid>` will override it.\n \n --continue::\n -r::\ndiff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt\nindex 5d750314b2..4c20e11aba 100644\n--- a/Documentation/git-cherry-pick.txt\n+++ b/Documentation/git-cherry-pick.txt\n@@ -9,7 +9,8 @@ SYNOPSIS\n --------\n [verse]\n 'git cherry-pick' [--edit] [-n] [-m parent-number] [-s] [-x] [--ff]\n-\t\t  [-S[<keyid>]] <commit>...\n+\t\t  [--sign] [(--sign-type <signType>)]\n+\t\t  [(--sign-option <token>[=<value>])...] <commit>...\n 'git cherry-pick' (--continue | --skip | --abort | --quit)\n \n DESCRIPTION\n@@ -107,14 +108,38 @@ effect to your index in a row.\n \tAdd a `Signed-off-by` trailer at the end of the commit message.\n \tSee the signoff option in linkgit:git-commit[1] for more information.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n---no-gpg-sign::\n-\tGPG-sign commits. The `keyid` argument is optional and\n-\tdefaults to the committer identity; if specified, it must be\n-\tstuck to the option without a space. `--no-gpg-sign` is useful to\n-\tcountermand both `commit.gpgSign` configuration variable, and\n-\tearlier `--gpg-sign`.\n+-S::\n+--sign::\n+--no-sign::\n+--gpg-sign[=<keyid>] (deprecated)::\n+--no-gpg-sign (deprecated)::\n+\tCryptographically sign commits. The `keyid` argument is deprecated\n+\tand the preferred way is to specify this as a configuration variable\n+\tas an option for the signing tool you use. For OpenPGP, you would\n+\tspecify this using 'sign.openpgp.options.identifier = <keyid>'. If\n+\tyou must pass the `keyid` on the command line, use\n+\t`--sign-option identifier=<keyid>`. For backwards compatibility, if\n+\tthe signature type is 'openpgp' or 'x509' and the `keyid` is\n+\tspecified, it is passed as if `--sign-option identifier=<keyid>` is\n+\talso specified. The `--no-sign` option is usefult to countermand both\n+\t'commit.sign' configuration variable and earlier `--sign` command line\n+\tswitches.\n+\n+--sign-type <signType>::\n+\tSpecifies the signature type to create when cryptographically signing\n+\tcommits. There must be a corresponding configuration block\n+\t'sign.<signType>' with at least 'sign.<signType>.program' specified.\n+\tFor backwards compatibility, 'openpgp' is assumed if the sign type\n+\tis not specified.\n+\n+--sign-option <token>[=<value>]::\n+\tSpecify an option to pass to the cryptographic signing tool using the\n+\tOPTION command in cryptographic signing protocol. Any number of options\n+\tmay be specified on the command line and they will override\n+\tany corresponding configuration variables with the same name. For\n+\texample, if the signature type is 'openpgp' and the configuration\n+\tvariable 'sign.openpgp.options.identifier' is set then\n+\t`--sign-option identifier=<keyid>` will override it.\n \n --ff::\n \tIf the current HEAD is the same as the parent of the\ndiff --git a/Documentation/git-commit-tree.txt b/Documentation/git-commit-tree.txt\nindex 2e2c581098..c7911de70a 100644\n--- a/Documentation/git-commit-tree.txt\n+++ b/Documentation/git-commit-tree.txt\n@@ -10,8 +10,9 @@ SYNOPSIS\n --------\n [verse]\n 'git commit-tree' <tree> [(-p <parent>)...]\n-'git commit-tree' [(-p <parent>)...] [-S[<keyid>]] [(-m <message>)...]\n-\t\t  [(-F <file>)...] <tree>\n+'git commit-tree' [(-p <parent>)...] [--sign]\n+\t\t  [(--sign-type <signType>)] [(--sign-option <token>[=<value])...]\n+\t\t  [(-m <message>)...] [(-F <file>)...] <tree>\n \n \n DESCRIPTION\n@@ -59,13 +60,38 @@ OPTIONS\n \tfrom the standard input. This can be given more than once and the\n \tcontent of each file becomes its own paragraph.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n---no-gpg-sign::\n-\tGPG-sign commits. The `keyid` argument is optional and\n-\tdefaults to the committer identity; if specified, it must be\n-\tstuck to the option without a space. `--no-gpg-sign` is useful to\n-\tcountermand a `--gpg-sign` option given earlier on the command line.\n+-S::\n+--sign::\n+--no-sign::\n+--gpg-sign[=<keyid>] (deprecated)::\n+--no-gpg-sign (deprecated)::\n+\tCryptographically sign commits. The `keyid` argument is deprecated\n+\tand the preferred way is to specify this as a configuration variable\n+\tas an option for the signing tool you use. For OpenPGP, you would\n+\tspecify this using 'sign.openpgp.options.identifier = <keyid>'. If\n+\tyou must pass the `keyid` on the command line, use\n+\t`--sign-option identifier=<keyid>`. For backwards compatibility, if\n+\tthe signature type is 'openpgp' or 'x509' and the `keyid` is\n+\tspecified, it is passed as if `--sign-option identifier=<keyid>` is\n+\talso specified. The `--no-sign` option is usefult to countermand both\n+\t'commit.sign' configuration variable and earlier `--sign` command line\n+\tswitches.\n+\n+--sign-type <signType>::\n+\tSpecifies the signature type to create when cryptographically signing\n+\tcommits. There must be a corresponding configuration block\n+\t'sign.<signType>.*' with at least 'sign.<signType>.program' specified.\n+\tFor backwards compatibility, 'openpgp' is assumed if the sign type\n+\tis not specified.\n+\n+--sign-option <token>[=<value>]::\n+\tSpecify an option to pass to the cryptographic signing tool using the\n+\tOPTION command in cryptographic signing protocol. Any number of\n+\toptions may be specified on the command line and they will override\n+\tany corresponding configuration variables with the same name. For\n+\texample, if the signature type is 'openpgp' and the configuration\n+\tvariable 'sign.openpgp.options.identifier' is set then\n+\t`--sign-option identifier=<keyid>` will override it.\n \n Commit Information\n ------------------\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex 340c5fbb48..69ae92c201 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -14,7 +14,8 @@ SYNOPSIS\n \t   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]\n \t   [--date=<date>] [--cleanup=<mode>] [--[no-]status]\n \t   [-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]\n-\t   [(--trailer <token>[(=|:)<value>])...] [-S[<keyid>]]\n+\t   [(--trailer <token>[(=|:)<value>])...] [--sign]\n+\t   [(--sign-type <signType>)] [(--sign-option <token>[=<value])...]\n \t   [--] [<pathspec>...]\n \n DESCRIPTION\n@@ -385,14 +386,38 @@ changes to tracked files.\n \tcommit message template when using an editor to prepare the\n \tdefault commit message.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n---no-gpg-sign::\n-\tGPG-sign commits. The `keyid` argument is optional and\n-\tdefaults to the committer identity; if specified, it must be\n-\tstuck to the option without a space. `--no-gpg-sign` is useful to\n-\tcountermand both `commit.gpgSign` configuration variable, and\n-\tearlier `--gpg-sign`.\n+-S::\n+--sign::\n+--no-sign::\n+--gpg-sign[=<keyid>] (deprecated)::\n+--no-gpg-sign (deprecated)::\n+\tCryptographically sign commits. The `keyid` argument is deprecated\n+\tand the preferred way is to specify this as a configuration variable\n+\tas an option for the signing tool you use. For OpenPGP, you would\n+\tspecify this using 'sign.openpgp.options.identifier = <keyid>'. If\n+\tyou must pass the `keyid` on the command line, use\n+\t`--sign-option identifier=<keyid>`. For backwards compatibility, if\n+\tthe signature type is 'openpgp' or 'x509' and the `keyid` is\n+\tspecified, it is passed as if `--sign-option identifier=<keyid>` is\n+\talso specified. The `--no-sign` option is usefult to countermand both\n+\t'commit.sign' configuration variable and earlier `--sign` command line\n+\tswitches.\n+\n+--sign-type <signType>::\n+\tSpecifies the signature type to create when cryptographically signing\n+\tcommits. There must be a corresponding configuration block\n+\t'sign.<signType>.*' with at least 'sign.<signType>.program' specified.\n+\tFor backwards compatibility, 'openpgp' is assumed if the sign type\n+\tis not specified.\n+\n+--sign-option <token>[=<value>]::\n+\tSpecify an option to pass to the cryptographic signing tool using the\n+\tOPTION command in cryptographic signing protocol. Any number of\n+\toptions may be specified on the command line and they will override\n+\tany corresponding configuration variables with the same name. For\n+\texample, if the signature type is 'openpgp' and the configuration\n+\tvariable 'sign.openpgp.options.identifier' is set then\n+\t`--sign-option identifier=<keyid>` will override it.\n \n \\--::\n \tDo not interpret any more arguments as options.\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex 39cfa05b28..5c8e302bd8 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -854,7 +854,7 @@ not interpreted by Git.  Currently they must be encoded in UTF-8,\n as fast-import does not permit other encodings to be specified.\n \n Signing annotated tags during import from within fast-import is not\n-supported.  Trying to include your own PGP/GPG signature is not\n+supported.  Trying to include your own cryptographic signature is not\n recommended, as the frontend does not (easily) have access to the\n complete set of bytes which normally goes into such a signature.\n If signing is required, create lightweight tags from within fast-import with\ndiff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt\nindex 2ae2478de7..fcbfd23acf 100644\n--- a/Documentation/git-for-each-ref.txt\n+++ b/Documentation/git-for-each-ref.txt\n@@ -254,7 +254,7 @@ contents:body::\n \tthe \"subject\".\n \n contents:signature::\n-\tThe optional GPG signature of the tag.\n+\tThe optional cryptographic signature of the tag.\n \n contents:lines=N::\n \tThe first `N` lines of the message.\ndiff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt\nindex 466a697519..19b8998195 100644\n--- a/Documentation/git-mktag.txt\n+++ b/Documentation/git-mktag.txt\n@@ -48,18 +48,34 @@ OPTIONS\n Tag Format\n ----------\n A tag signature file, to be fed to this command's standard input,\n-has a very simple fixed format: four lines of\n+must have at least these four lines:\n \n-  object <hash>\n-  type <typename>\n-  tag <tagname>\n-  tagger <tagger>\n+object <hash>\n+type <typename>\n+tag <tagname>\n+tagger <tagger>\n \n followed by some 'optional' free-form message (some tags created\n by older Git may not have `tagger` line).  The message, when it\n-exists, is separated by a blank line from the header.  The\n-message part may contain a signature that Git itself doesn't\n-care about, but that can be verified with gpg.\n+exists, is separated by a blank line from the header.\n+\n+A cryptographically signed tag may be created by including a\n+signature formatted using the version 2 format:\n+\n+object <hash>\n+type <typename>\n+tag <tagname>\n+tagger <tagger>\n+signtype openpgp\n+sign -----BEGIN PGP SIGNATURE-----%0a\n+ %0a\n+ iHUEABYKAB0WIQTXto4BPKlfA2YYS5Pn3hDaTgk8fAUCX5C+ugAKCRDn3hDaTgk8%0a\n+ fOk8AQCRGkdNGMXhJ95e5QIHk44rvfNsyibxY6ZvTXdLQJvt/gEAlFCeEM3SfaDL%0a\n+ 8RQR368L0+caDlaZW51VZVP2UBXP6w0=%0a\n+ =1Fby%0a\n+ -----END PGP SIGNATURE-----%0a\n+\n+followed by an optional free-form message.\n \n GIT\n ---\ndiff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt\nindex 55af6fd24e..c9654dff6e 100644\n--- a/Documentation/git-rebase.txt\n+++ b/Documentation/git-rebase.txt\n@@ -9,8 +9,10 @@ SYNOPSIS\n --------\n [verse]\n 'git rebase' [-i | --interactive] [<options>] [--exec <cmd>]\n-\t[--onto <newbase> | --keep-base] [<upstream> [<branch>]]\n+\t [--sign] [(--sign-type <signType>)] [(--sign-option <token>[=<value])...]\n+\t [--onto <newbase> | --keep-base] [<upstream> [<branch>]]\n 'git rebase' [-i | --interactive] [<options>] [--exec <cmd>] [--onto <newbase>]\n+\t [--sign] [(--sign-type <signType>)] [(--sign-option <token>[=<value])...]\n \t--root [<branch>]\n 'git rebase' (--continue | --skip | --abort | --quit | --edit-todo | --show-current-patch)\n \n@@ -379,14 +381,38 @@ See also INCOMPATIBLE OPTIONS below.\n \tAllow the rerere mechanism to update the index with the\n \tresult of auto-conflict resolution if possible.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n---no-gpg-sign::\n-\tGPG-sign commits. The `keyid` argument is optional and\n-\tdefaults to the committer identity; if specified, it must be\n-\tstuck to the option without a space. `--no-gpg-sign` is useful to\n-\tcountermand both `commit.gpgSign` configuration variable, and\n-\tearlier `--gpg-sign`.\n+-S::\n+--sign::\n+--no-sign::\n+--gpg-sign[=<keyid>] (deprecated)::\n+--no-gpg-sign (deprecated)::\n+\tCryptographically sign commits. The `keyid` argument is deprecated\n+\tand the preferred way is to specify this as a configuration variable\n+\tas an option for the signing tool you use. For OpenPGP, you would\n+\tspecify this using 'sign.openpgp.options.identifier = <keyid>'. If\n+\tyou must pass the `keyid` on the command line, use\n+\t`--sign-option identifier=<keyid>`. For backwards compatibility, if\n+\tthe signature type is 'openpgp' or 'x509' and the `keyid` is\n+\tspecified, it is passed as if `--sign-option identifier=<keyid>` is\n+\talso specified. The `--no-sign` option is usefult to countermand both\n+\t'commit.sign' configuration variable and earlier `--sign` command line\n+\tswitches.\n+\n+--sign-type <signType>::\n+\tSpecifies the signature type to create when cryptographically signing\n+\tcommits. There must be a corresponding configuration block\n+\t'sign.<signType>.*' with at least 'sign.<signType>.program' specified.\n+\tFor backwards compatibility, 'openpgp' is assumed if the sign type\n+\tis not specified.\n+\n+--sign-option <token>[=<value>]::\n+\tSpecify an option to pass to the cryptographic signing tool using the\n+\tOPTION command in cryptographic signing protocol. Any number of\n+\toptions may be specified on the command line and they will override\n+\tany corresponding configuration variables with the same name. For\n+\texample, if the signature type is 'openpgp' and the configuration\n+\tvariable 'sign.openpgp.options.identifier' is set then\n+\t`--sign-option identifier=<keyid>` will override it.\n \n -q::\n --quiet::\ndiff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt\nindex bb92a4a451..5ea0ee9bd3 100644\n--- a/Documentation/git-revert.txt\n+++ b/Documentation/git-revert.txt\n@@ -8,7 +8,9 @@ git-revert - Revert some existing commits\n SYNOPSIS\n --------\n [verse]\n-'git revert' [--[no-]edit] [-n] [-m parent-number] [-s] [-S[<keyid>]] <commit>...\n+'git revert' [--[no-]edit] [-n] [-m parent-number] [-s]\n+\t[--sign] [(--sign-type <signType>)] [(--sign-option <token>[=<value])...]\n+\t<commit>...\n 'git revert' (--continue | --skip | --abort | --quit)\n \n DESCRIPTION\n@@ -88,14 +90,38 @@ more details.\n This is useful when reverting more than one commits'\n effect to your index in a row.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n---no-gpg-sign::\n-\tGPG-sign commits. The `keyid` argument is optional and\n-\tdefaults to the committer identity; if specified, it must be\n-\tstuck to the option without a space. `--no-gpg-sign` is useful to\n-\tcountermand both `commit.gpgSign` configuration variable, and\n-\tearlier `--gpg-sign`.\n+-S::\n+--sign::\n+--no-sign::\n+--gpg-sign[=<keyid>] (deprecated)::\n+--no-gpg-sign (deprecated)::\n+\tCryptographically sign commits. The `keyid` argument is deprecated\n+\tand the preferred way is to specify this as a configuration variable\n+\tas an option for the signing tool you use. For OpenPGP, you would\n+\tspecify this using 'sign.openpgp.options.identifier = <keyid>'. If\n+\tyou must pass the `keyid` on the command line, use\n+\t`--sign-option identifier=<keyid>`. For backwards compatibility, if\n+\tthe signature type is 'openpgp' or 'x509' and the `keyid` is\n+\tspecified, it is passed as if `--sign-option identifier=<keyid>` is\n+\talso specified. The `--no-sign` option is usefult to countermand both\n+\t'commit.sign' configuration variable and earlier `--sign` command line\n+\tswitches.\n+\n+--sign-type <signType>::\n+\tSpecifies the signature type to create when cryptographically signing\n+\tcommits. There must be a corresponding configuration block\n+\t'sign.<signType>.*' with at least 'sign.<signType>.program' specified.\n+\tFor backwards compatibility, 'openpgp' is assumed if the sign type\n+\tis not specified.\n+\n+--sign-option <token>[=<value>]::\n+\tSpecify an option to pass to the cryptographic signing tool using the\n+\tOPTION command in cryptographic signing protocol. Any number of\n+\toptions may be specified on the command line and they will override\n+\tany corresponding configuration variables with the same name. For\n+\texample, if the signature type is 'openpgp' and the configuration\n+\tvariable 'sign.openpgp.options.identifier' is set then\n+\t`--sign-option identifier=<keyid>` will override it.\n \n -s::\n --signoff::\ndiff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt\nindex 31a97a1b6c..764939ec93 100644\n--- a/Documentation/git-tag.txt\n+++ b/Documentation/git-tag.txt\n@@ -3,13 +3,14 @@ git-tag(1)\n \n NAME\n ----\n-git-tag - Create, list, delete or verify a tag object signed with GPG\n+git-tag - Create, list, delete or verify a tag object\n \n \n SYNOPSIS\n --------\n [verse]\n-'git tag' [-a | -s | -u <keyid>] [-f] [-m <msg> | -F <file>] [-e]\n+'git tag' [-a] [--sign] [(--sign-type <signType>)] \n+  [(--sign-option <token>[=<value])...][-f] [-m <msg> | -F <file>] [-e]\n \t<tagname> [<commit> | <object>]\n 'git tag' -d <tagname>...\n 'git tag' [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]\n@@ -26,26 +27,23 @@ to delete, list or verify tags.\n \n Unless `-f` is given, the named tag must not yet exist.\n \n-If one of `-a`, `-s`, or `-u <keyid>` is passed, the command\n-creates a 'tag' object, and requires a tag message.  Unless\n-`-m <msg>` or `-F <file>` is given, an editor is started for the user to type\n-in the tag message.\n+If one of `-a`, is passed, the command creates a 'tag' object, and\n+requires a tag message.  Unless `-m <msg>` or `-F <file>` is given,\n+an editor is started for the user to type in the tag message.\n \n-If `-m <msg>` or `-F <file>` is given and `-a`, `-s`, and `-u <keyid>`\n-are absent, `-a` is implied.\n+If `-m <msg>` or `-F <file>` is given and `-a` is absent, `-a` is\n+implied.\n \n Otherwise, a tag reference that points directly at the given object\n (i.e., a lightweight tag) is created.\n \n-A GnuPG signed tag object will be created when `-s` or `-u\n-<keyid>` is used.  When `-u <keyid>` is not used, the\n-committer identity for the current user is used to find the\n-GnuPG key for signing. \tThe configuration variable `gpg.program`\n-is used to specify custom GnuPG binary.\n+A cryptographically signed object is created when `--sign` is used.\n+The type of signature to create may be specified using `--sign-type`\n+and options specified using `--sign-option`.\n \n-Tag objects (created with `-a`, `-s`, or `-u`) are called \"annotated\"\n+Tag objects (created with `-a` or `--sign`) are called \"annotated\"\n tags; they contain a creation date, the tagger name and e-mail, a\n-tagging message, and an optional GnuPG signature. Whereas a\n+tagging message, and an optional cryptographic signature. Whereas a\n \"lightweight\" tag is simply a name for an object (usually a commit\n object).\n \n@@ -61,20 +59,41 @@ OPTIONS\n --annotate::\n \tMake an unsigned, annotated tag object\n \n--s::\n+-S::\n --sign::\n-\tMake a GPG-signed tag, using the default e-mail address's key.\n-\tThe default behavior of tag GPG-signing is controlled by `tag.gpgSign`\n-\tconfiguration variable if it exists, or disabled otherwise.\n-\tSee linkgit:git-config[1].\n-\n --no-sign::\n-\tOverride `tag.gpgSign` configuration variable that is\n-\tset to force each and every tag to be signed.\n-\n--u <keyid>::\n---local-user=<keyid>::\n-\tMake a GPG-signed tag, using the given key.\n+-s (deprecated)::\n+\tCryptographically sign the tag. The `--no-sign` option is usefult to\n+\tcountermand both 'commit.sign' configuration variable and earlier \n+\t`--sign` command line switches.\n+\n+-u <keyid> (deprecated)::\n+--local-user=<keyid> (deprecated)::\n+\tBoth of these options are deprecated and should no longer be used.\n+\tThe preferred way is to specify this as a configuration variable as\n+\tan option for the signing tool you use. For OpenPGP, you would\n+\tspecify this using 'sign.openpgp.options.identifier = <keyid>'. If\n+\tyou must pass the `keyid` on the command line, use\n+\t`--sign-option identifier=<keyid>`. For backwards compatibility, if\n+\tthe signature type is 'openpgp' or 'x509' and the `keyid` is\n+\tspecified, it is passed as if `--sign-option identifier=<keyid>` is\n+\talso specified. \n+\n+--sign-type <signType>::\n+\tSpecifies the signature type to create when cryptographically signing\n+\tcommits. There must be a corresponding configuration block\n+\t'sign.<signType>.*' with at least 'sign.<signType>.program' specified.\n+\tFor backwards compatibility, 'openpgp' is assumed if the sign type\n+\tis not specified.\n+\n+--sign-option <token>[=<value>]::\n+\tSpecify an option to pass to the cryptographic signing tool using the\n+\tOPTION command in cryptographic signing protocol. Any number of\n+\toptions may be specified on the command line and they will override\n+\tany corresponding configuration variables with the same name. For\n+\texample, if the signature type is 'openpgp' and the configuration\n+\tvariable 'sign.openpgp.options.identifier' is set then\n+\t`--sign-option identifier=<keyid>` will override it.\n \n -f::\n --force::\n@@ -86,7 +105,7 @@ OPTIONS\n \n -v::\n --verify::\n-\tVerify the GPG signature of the given tag names.\n+\tVerify the cryptographic signature of the given tag names.\n \n -n<num>::\n \t<num> specifies how many lines from the annotation, if any,\n@@ -213,15 +232,24 @@ This option is only applicable when listing tags without annotation lines.\n \n CONFIGURATION\n -------------\n-By default, 'git tag' in sign-with-default mode (-s) will use your\n-committer identity (of the form `Your Name <your@email.address>`) to\n-find a key.  If you want to use a different default key, you can specify\n-it in the repository configuration as follows:\n-\n--------------------------------------\n-[user]\n-    signingKey = <gpg-keyid>\n--------------------------------------\n+By default, 'git tag' in sign-with-default mode (-S) determines the\n+type of signature from the `sign.default` config option and/or the\n+`--sign-type` command line option. The identifier for the signature\n+is then determined by the `sign.<signType>.options.identifier` config\n+option and/or the `--sign-option identifier=<keyid>` command line\n+option.\n+\n+For backwards compatibility, if you are still using the deprecated\n+`user.signingKey` config option and enable tag signing, the behavior\n+is as if you also specified the following command line options:\n+\n+\t--sign-type openpgp\n+\t--sign-option armored=true \n+\t--sign-option detached=true\n+\t--sign-option identifier=<keyid>\n+\n+which emulates the original signing behavior of running\n+`gpg -bsau <keyid>` to create the signature.\n \n `pager.tag` is only respected when listing tags, i.e., when `-l` is\n used or implied. The default is to use a pager.\ndiff --git a/Documentation/git-verify-commit.txt b/Documentation/git-verify-commit.txt\nindex 92097f6673..4b2e8ea909 100644\n--- a/Documentation/git-verify-commit.txt\n+++ b/Documentation/git-verify-commit.txt\n@@ -3,7 +3,7 @@ git-verify-commit(1)\n \n NAME\n ----\n-git-verify-commit - Check the GPG signature of commits\n+git-verify-commit - Check the cryptographic signature of commits\n \n SYNOPSIS\n --------\n@@ -12,13 +12,13 @@ SYNOPSIS\n \n DESCRIPTION\n -----------\n-Validates the GPG signature created by 'git commit -S'.\n+Validates the cryptographic signature created by 'git commit -S'.\n \n OPTIONS\n -------\n --raw::\n-\tPrint the raw gpg status output to standard error instead of the normal\n-\thuman-readable output.\n+\tPrint the raw signature verification status output to standard error \n+\tinstead of the normal human-readable output.\n \n -v::\n --verbose::\ndiff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.txt\nindex 0b8075dad9..939cf8dc3a 100644\n--- a/Documentation/git-verify-tag.txt\n+++ b/Documentation/git-verify-tag.txt\n@@ -3,7 +3,7 @@ git-verify-tag(1)\n \n NAME\n ----\n-git-verify-tag - Check the GPG signature of tags\n+git-verify-tag - Check the cryptographic signature of tags\n \n SYNOPSIS\n --------\n@@ -12,13 +12,13 @@ SYNOPSIS\n \n DESCRIPTION\n -----------\n-Validates the gpg signature created by 'git tag'.\n+Validates the cryptographic signature created by 'git tag'.\n \n OPTIONS\n -------\n --raw::\n-\tPrint the raw gpg status output to standard error instead of the normal\n-\thuman-readable output.\n+\tPrint the raw signature verification status output to standard error\n+\tinstead of the normal human-readable output.\n \n -v::\n --verbose::\ndiff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt\nindex eb0aabd396..ba521f90d3 100644\n--- a/Documentation/merge-options.txt\n+++ b/Documentation/merge-options.txt\n@@ -59,14 +59,38 @@ could instead be resolved as a fast-forward.\n With `--ff-only`, resolve the merge as a fast-forward when possible.\n When not possible, refuse to merge and exit with a non-zero status.\n \n--S[<keyid>]::\n---gpg-sign[=<keyid>]::\n---no-gpg-sign::\n-\tGPG-sign the resulting merge commit. The `keyid` argument is\n-\toptional and defaults to the committer identity; if specified,\n-\tit must be stuck to the option without a space. `--no-gpg-sign`\n-\tis useful to countermand both `commit.gpgSign` configuration variable,\n-\tand earlier `--gpg-sign`.\n+-S::\n+--sign::\n+--no-sign::\n+--gpg-sign[=<keyid>] (deprecated)::\n+--no-gpg-sign (deprecated)::\n+\tCryptographically sign commits. The `keyid` argument is deprecated\n+\tand the preferred way is to specify this as a configuration variable\n+\tas an option for the signing tool you use. For OpenPGP, you would\n+\tspecify this using 'sign.openpgp.options.identifier = <keyid>'. If\n+\tyou must pass the `keyid` on the command line, use\n+\t`--sign-option identifier=<keyid>`. For backwards compatibility, if\n+\tthe signature type is 'openpgp' or 'x509' and the `keyid` is\n+\tspecified, it is passed as if `--sign-option identifier=<keyid>` is\n+\talso specified. The `--no-sign` option is usefult to countermand both\n+\t'commit.sign' configuration variable and earlier `--sign` command line\n+\tswitches.\n+\n+--sign-type <signType>::\n+\tSpecifies the signature type to create when cryptographically signing\n+\tcommits. There must be a corresponding configuration block\n+\t'sign.<signType>.*' with at least 'sign.<signType>.program' specified.\n+\tFor backwards compatibility, 'openpgp' is assumed if the sign type\n+\tis not specified.\n+\n+--sign-option <token>[=<value>]::\n+\tSpecify an option to pass to the cryptographic signing tool using the\n+\tOPTION command in cryptographic signing protocol. Any number of\n+\toptions may be specified on the command line and they will override\n+\tany corresponding configuration variables with the same name. For\n+\texample, if the signature type is 'openpgp' and the configuration\n+\tvariable 'sign.openpgp.options.identifier' is set then\n+\t`--sign-option identifier=<keyid>` will override it.\n \n --log[=<n>]::\n --no-log::\ndiff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt\nindex cd697f508c..229ddabbd7 100644\n--- a/Documentation/pretty-formats.txt\n+++ b/Documentation/pretty-formats.txt\n@@ -235,7 +235,7 @@ The placeholders are:\n ifndef::git-rev-list[]\n '%N':: commit notes\n endif::git-rev-list[]\n-'%GG':: raw verification message from GPG for a signed commit\n+'%GG':: raw verification message for a cryptographically signed commit\n '%G?':: show \"G\" for a good (valid) signature,\n \t\"B\" for a bad signature,\n \t\"U\" for a good signature with unknown validity,\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 27ddaf84a1..45bd13bb25 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -93,4 +93,4 @@ endif::git-rev-list[]\n \n --show-signature::\n \tCheck the validity of a signed commit object by passing the signature\n-\tto `gpg --verify` and show the output.\n+\tto associated verification tool and show the output.\ndiff --git a/Documentation/technical/hash-function-transition.txt b/Documentation/technical/hash-function-transition.txt\nindex 7c1630bf83..d9bd4082c3 100644\n--- a/Documentation/technical/hash-function-transition.txt\n+++ b/Documentation/technical/hash-function-transition.txt\n@@ -409,17 +409,16 @@ send-pack.\n \n Signed Commits\n ~~~~~~~~~~~~~~\n-We add a new field \"gpgsig-sha256\" to the commit object format to allow\n-signing commits without relying on SHA-1. It is similar to the\n-existing \"gpgsig\" field. Its signed payload is the SHA-256 content of the\n-commit object with any \"gpgsig\" and \"gpgsig-sha256\" fields removed.\n+We use the new signature format whenever signing commits without relying\n+on SHA-1. The new format adds a 'signtype' field, zero or more 'signoption'\n+fields, and one 'sign' field to commit objects. This allows for the 'gpgsig'\n+field to coexist if needed.\n \n This means commits can be signed\n \n 1. using SHA-1 only, as in existing signed commit objects\n-2. using both SHA-1 and SHA-256, by using both gpgsig-sha256 and gpgsig\n-   fields.\n-3. using only SHA-256, by only using the gpgsig-sha256 field.\n+2. using both SHA-1 and SHA-256, by using both gpgsig and the V2 format.\n+3. using only SHA-256, by only using the V2 format.\n \n Old versions of \"git verify-commit\" can verify the gpgsig signature in\n cases (1) and (2) without modifications and view case (3) as an\n@@ -427,17 +426,16 @@ ordinary unsigned commit.\n \n Signed Tags\n ~~~~~~~~~~~\n-We add a new field \"gpgsig-sha256\" to the tag object format to allow\n-signing tags without relying on SHA-1. Its signed payload is the\n-SHA-256 content of the tag with its gpgsig-sha256 field and \"-----BEGIN PGP\n-SIGNATURE-----\" delimited in-body signature removed.\n+We use the new signature format whenever signing tags without relying\n+on SHA-1. The new format adds a 'signtype' field, zero or more 'signoption'\n+fields, and one 'sign' field to tag objects. This allows for the in-body\n+SHA-1 signature to coexist if needed.\n \n This means tags can be signed\n \n 1. using SHA-1 only, as in existing signed tag objects\n-2. using both SHA-1 and SHA-256, by using gpgsig-sha256 and an in-body\n-   signature.\n-3. using only SHA-256, by only using the gpgsig-sha256 field.\n+2. using both SHA-1 and SHA-256, by using both gpgsig and the V2 format.\n+3. using only SHA-256, by only using the V2 format.\n \n Mergetag embedding\n ~~~~~~~~~~~~~~~~~~\n@@ -631,8 +629,9 @@ Transition plan\n Some initial steps can be implemented independently of one another:\n \n - adding a hash function API (vtable)\n-- teaching fsck to tolerate the gpgsig-sha256 field\n-- excluding gpgsig-* from the fields copied by \"git commit --amend\"\n+- teaching fsck to tolerate the 'signtype', 'signoption' and 'sign' tags\n+- excluding 'signtype', 'signoption' and 'sign' from the fields copied\n+  by \"git commit --amend\"\n - annotating tests that depend on SHA-1 values with a SHA1 test\n   prerequisite\n - using \"struct object_id\", GIT_MAX_RAWSZ, and GIT_MAX_HEXSZ\ndiff --git a/Documentation/technical/signature-format-v2.txt b/Documentation/technical/signature-format-v2.txt\nnew file mode 100644\nindex 0000000000..8628402e29\n--- /dev/null\n+++ b/Documentation/technical/signature-format-v2.txt\n@@ -0,0 +1,232 @@\n+Git Signature Format, Version 2\n+===============================\n+\n+Overview\n+--------\n+\n+Git supports cryptographic signatures on objecs (e.g. tags, commits, mergetags)\n+and transactions (e.g. pushes). The first version of these signatures were\n+always created using gpg or gpgsm and resulted in OpenPGP signatures with known\n+formats that made parsing signatures for verification simple using string\n+matching. Version 2 of signature format is designed to work hand-in-hand with\n+the new cryptographic signing/verification protocol and supports any possible\n+signature format while still being easily parseable for verification purposes.\n+\n+Version 1 Format\n+----------------\n+\n+The first verion of the protocol is documented in the signature-format.txt\n+file. The relevant details from that document define the fields used to\n+identify signatures in the meta data of objects and transations.\n+\n+Tags\n+~~~~\n+\n+In tags, signatures are stored \"in-body\" immediately following the tag body.\n+To parse a signature from a tag, Git string matches for `-----BEGIN PGP\n+SIGNATURE-----` and `-----END PGP SIGNATURE-----` that mark the begining and\n+ending of a signature. The only difference between gpg and gpgsm signatures is\n+that gpgsm signatures use the strings `-----BEGIN SIGNED MESSAGE-----` and\n+`-----END SIGNED MESSAGE-----` instead.\n+\n+The transition from SHA1 to SHA256 has complicated this somewhat by adding a\n+new \"gpgsig-sha256\" field that stores the signature whenever the SHA256 digest\n+algorithm is used. It is possible to have both the \"in-body\" signature created\n+when SHA-1 digest is used as well as the signature stored as the value for the\n+\"gpgsig-sha256\" field when SHA256 digest is used.\n+\n+Either way, the content that gets sent to the signing tool is the full object\n+data, fields and body, without including the \"gpgsig-sha256\" field or any\n+in-body signature data.\n+\n+Commits\n+~~~~~~~\n+\n+In commits, signatures are stored in the field named \"gpgsig\" when SHA-1 digest\n+is used and \"gpgsig-sha256\" when SHA256 digest is used. Parsing signatures in\n+commits is also done with string matching of the BEGIN/END strings marking\n+OpenPGP signatures even though they are stored as fields.\n+\n+Mergetags\n+~~~~~~~~~\n+\n+In mergtags, the whole signed tag object is stored in the field named\n+\"mergetag\" and the output of verifying the signature is appended to the body of\n+the mergetag as comment lines starting with '#'.\n+\n+Version 2 Format\n+----------------\n+\n+The goals of the version 2 format are as follows:\n+\n+- Backwards Compatible with version 1 without any intervention.\n+- Eliminate signature-format-specific string matching for detecting/parsing\n+  version 2 signatures.\n+- Use fields for storing signatures in all objects and transactions.\n+- Have a field that identifies the signature format.\n+- Have fields that store options required by the verification tool.\n+- Store signature data verbatim as created with the signing tool with escaped\n+  newlines and carriage returns.\n+\n+Fields\n+~~~~~~\n+\n+The version 2 format uses three new fields listed below:\n+\n+- signtype <signature format name>\n+- signoption <token> [= <value>]\n+- sign <multiline signature data>\n+\n+A complete signature must include exactly one `signtype` field, zero or more\n+`signoption` fields and one `sign` field.\n+\n+The `signtype` field has a string value that identifies the type of signature\n+that is stored in the object. This string is case-insensitive and is used to\n+identify which configuration settings are to used when verifying the signature.\n+The corresponding configuration settings are in the config file as:\n+'sign.<signType>.options.*'. The 'sign' field stores the text-encoded signature\n+from the signing tool with any newlines and carriage returns escaped as '%0a'\n+and '%0d' respectively. Whitespace is significant in digital signatures and\n+the protocol for sending/receiving data to/from signing and verification tools\n+requires that newlines and carriage returns are escaped. By storing the escaped\n+version in the 'sign' field, we avoid extra processing and error-prone\n+escaping.\n+\n+The introduction of the 'signoption' field is necessary for Git to remain\n+agnostic to the tools used for signing and verification of cryptographic\n+signatures. Some signign tools do not produce cryptographic signatures that\n+include all of the data needed to verify the signature. A good example of this\n+is the minisign tool (https://jedisct1.github.io/minisign/) which requires the\n+public key to be supplied to the verification operation. In that case, the\n+signing operation would return to Git a 'signoption' field along with the\n+'signtype' and 'sign' fields to be stored in the Git object. When Git verifies\n+the signature, it will parse the 'signoption' fields and send them to the\n+verification tool as OPTION commands. In this case it will send the public key\n+along with the signature for verification. This design allows for arbitrary\n+options to be stored in the Git object by the signing tool that will get passed\n+to the verification tool later without Git knowing or understanding any details\n+of a particular signing tool.\n+\n+The order in which OPTION commands are sent to the signing and verification\n+tools is significant. OPTION commands that come later override OPTION commands\n+that came earlier and had the same token name. Git always sends OPTION commands\n+from the command line after the options from the config. In verification\n+operations, Git sends the options from the signed object first, before the\n+config and command line options. This ensures local control over option values.\n+An example would be if the sign.openpgp.options.minTrustLevel config option is\n+set to \"marginal\" and the command line `--sign-option minTrustLevel = full` is\n+issued. Git would first send an OPTION command setting \n+`minTrustLevel = marginal` from the config and then override that by later\n+sending an OPTION command setting `minTrustLevel = full` from the command line.\n+\n+The `sign` field is very similar to the old `gpgsig` field in commits. The data\n+is can be multi-line with subsequent lines starting with spaces to mark them as\n+additional data. The only difference is that the `sign` field stores signatures\n+with newlines and carriage returns escaped because whitespace is significate in\n+cryptographic signatures. Again, the idea is to keep Git completely agnostic to\n+the details of any cryptographic signing/verification tool so the signature\n+data must be escaped and stored verbatim in the object. This allows simple and\n+exact transmission of the signature data to the verification tool in the\n+future.\n+\n+Examples\n+~~~~~~~~\n+\n+Below are the examples taken from the Version 1 signature-format.txt\n+documentation and translated into objects that use the Version 2 format as an\n+example.\n+\n+Signed Tag:\n+\n+----\n+object 04b871796dc0420f8e7561a895b52484b701d51a\n+type commit\n+tag signedtag\n+tagger C O Mitter <committer@example.com> 1465981006 +0000\n+signtype openpgp\n+sign -----BEGIN PGP SIGNATURE-----%0a\n+ Version: GnuPG v1%0a\n+ %0a\n+ iQEcBAABAgAGBQJXYRhOAAoJEGEJLoW3InGJklkIAIcnhL7RwEb/+QeX9enkXhxn%0a\n+ rxfdqrvWd1K80sl2TOt8Bg/NYwrUBw/RWJ+sg/hhHp4WtvE1HDGHlkEz3y11Lkuh%0a\n+ 8tSxS3qKTxXUGozyPGuE90sJfExhZlW4knIQ1wt/yWqM+33E9pN4hzPqLwyrdods%0a\n+ q8FWEqPPUbSJXoMbRPw04S5jrLtZSsUWbRYjmJCHzlhSfFWW4eFd37uquIaLUBS0%0a\n+ rkC3Jrx7420jkIpgFcTI2s60uhSQLzgcCwdA2ukSYIRnjg/zDkj8+3h/GaROJ72x%0a\n+ lZyI6HWixKJkWw8lE9aAOD9TmTW9sFJwcVAzmAuFX2kUreDUKMZduGcoRYGpD7E=%0a\n+ =jpXa%0a\n+ -----END PGP SIGNATURE-----%0a\n+\n+signed tag\n+\n+signed tag message body\n+----\n+\n+\n+Signed Commit:\n+\n+----\n+tree eebfed94e75e7760540d1485c740902590a00332\n+parent 04b871796dc0420f8e7561a895b52484b701d51a\n+author A U Thor <author@example.com> 1465981137 +0000\n+committer C O Mitter <committer@example.com> 1465981137 +0000\n+signtype openpgp\n+sign -----BEGIN PGP SIGNATURE-----%0a\n+ Version: GnuPG v1%0a\n+ %0a\n+ iQEcBAABAgAGBQJXYRjRAAoJEGEJLoW3InGJ3IwIAIY4SA6GxY3BjL60YyvsJPh/%0a\n+ HRCJwH+w7wt3Yc/9/bW2F+gF72kdHOOs2jfv+OZhq0q4OAN6fvVSczISY/82LpS7%0a\n+ DVdMQj2/YcHDT4xrDNBnXnviDO9G7am/9OE77kEbXrp7QPxvhjkicHNwy2rEflAA%0a\n+ zn075rtEERDHr8nRYiDh8eVrefSO7D+bdQ7gv+7GsYMsd2auJWi1dHOSfTr9HIF4%0a\n+ HJhWXT9d2f8W+diRYXGh4X0wYiGg6na/soXc+vdtDYBzIxanRqjg8jCAeo1eOTk1%0a\n+ EdTwhcTZlI0x5pvJ3H0+4hA2jtldVtmPM4OTB0cTrEWBad7XV6YgiyuII73Ve3I=%0a\n+ =jKHM%0a\n+ -----END PGP SIGNATURE-----%0a\n+\n+signed commit\n+\n+signed commit message body\n+----\n+\n+\n+Signed Mergetag:\n+\n+----\n+tree c7b1cff039a93f3600a1d18b82d26688668c7dea\n+parent c33429be94b5f2d3ee9b0adad223f877f174b05d\n+parent 04b871796dc0420f8e7561a895b52484b701d51a\n+author A U Thor <author@example.com> 1465982009 +0000\n+committer C O Mitter <committer@example.com> 1465982009 +0000\n+mergetag object 04b871796dc0420f8e7561a895b52484b701d51a\n+ type commit\n+ tag signedtag\n+ tagger C O Mitter <committer@example.com> 1465981006 +0000\n+ signtype openpgp\n+ sign  -----BEGIN PGP SIGNATURE-----%0a\n+ Version: GnuPG v1%0a\n+ %0a\n+ iQEcBAABAgAGBQJXYRhOAAoJEGEJLoW3InGJklkIAIcnhL7RwEb/+QeX9enkXhxn%0a\n+ rxfdqrvWd1K80sl2TOt8Bg/NYwrUBw/RWJ+sg/hhHp4WtvE1HDGHlkEz3y11Lkuh%0a\n+ 8tSxS3qKTxXUGozyPGuE90sJfExhZlW4knIQ1wt/yWqM+33E9pN4hzPqLwyrdods%0a\n+ q8FWEqPPUbSJXoMbRPw04S5jrLtZSsUWbRYjmJCHzlhSfFWW4eFd37uquIaLUBS0%0a\n+ rkC3Jrx7420jkIpgFcTI2s60uhSQLzgcCwdA2ukSYIRnjg/zDkj8+3h/GaROJ72x%0a\n+ lZyI6HWixKJkWw8lE9aAOD9TmTW9sFJwcVAzmAuFX2kUreDUKMZduGcoRYGpD7E=%0a\n+ =jpXa%0a\n+ -----END PGP SIGNATURE-----%0a\n+\n+ signed tag\n+\n+ signed tag message body\n+\n+Merge tag 'signedtag' into downstream\n+\n+signed tag\n+\n+signed tag message body\n+\n+# Signature made Wed Jun 15 08:56:46 2016 UTC using RSA key ID B7227189\n+# Good signature from \"Eris Discordia <discord@example.net>\"\n+# WARNING: This key is not certified with a trusted signature!\n+#          There is no indication that the signature belongs to the owner.\n+# Primary key fingerprint: D4BE 2231 1AD3 131E 5EDA  29A4 6109 2E85 B722 7189\n+----\n+\ndiff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt\nindex f9e54b8674..a5922d0364 100644\n--- a/Documentation/user-manual.txt\n+++ b/Documentation/user-manual.txt\n@@ -2930,7 +2930,7 @@ There are four different types of objects: \"blob\", \"tree\", \"commit\", and\n - A <<def_tag_object,\"tag\" object>> symbolically identifies and can be\n   used to sign other objects. It contains the object name and type of\n   another object, a symbolic name (of course!) and, optionally, a\n-  signature.\n+  cryptographic signature.\n \n The object types in some more detail:\n \n@@ -3071,15 +3071,15 @@ parents of that commit, and all of those contents of the trees referred\n to by those commits.\n \n So to introduce some real trust in the system, the only thing you need\n-to do is to digitally sign just 'one' special note, which includes the\n-name of a top-level commit.  Your digital signature shows others\n-that you trust that commit, and the immutability of the history of\n-commits tells others that they can trust the whole history.\n+to do is to cryptographically sign just 'one' special note, which\n+includes the name of a top-level commit. Your cryptographic signature\n+shows others that you trust that commit, and the immutability of the\n+history of commits tells others that they can trust the whole history.\n \n In other words, you can easily validate a whole archive by just\n sending out a single email that tells the people the name (SHA-1 hash)\n-of the top commit, and digitally sign that email using something\n-like GPG/PGP.\n+of the top commit, and cryptographically sign that email using\n+something like GPG/PGP.\n \n To assist in this, Git also provides the tag object...\n \n@@ -3087,8 +3087,8 @@ To assist in this, Git also provides the tag object...\n ==== Tag Object\n \n A tag object contains an object, object type, tag name, the name of the\n-person (\"tagger\") who created the tag, and a message, which may contain\n-a signature, as can be seen using linkgit:git-cat-file[1]:\n+person (\"tagger\") who created the tag, an optional cryptographic\n+signature, and a message as can be seen using linkgit:git-cat-file[1]:\n \n ------------------------------------------------\n $ git cat-file tag v1.5.0\n@@ -3096,15 +3096,17 @@ object 437b1b20df4b356c9342dac8d38849f24ef44f27\n type commit\n tag v1.5.0\n tagger Junio C Hamano <junkio@cox.net> 1171411200 +0000\n+signtype openpgp\n+sign -----BEGIN PGP SIGNATURE-----%0a\n+ Version: GnuPG v1.4.6 (GNU/Linux)%0a\n+ %0a\n+ iD8DBQBF0lGqwMbZpPMRm5oRAuRiAJ9ohBLd7s2kqjkKlq1qqC57SbnmzQCdG4ui%0a\n+ nLE/L9aUXdWeTFPron96DLA=%0a\n+ =2E+0%0a\n+ -----END PGP SIGNATURE-----%0a\n \n-GIT 1.5.0\n------BEGIN PGP SIGNATURE-----\n-Version: GnuPG v1.4.6 (GNU/Linux)\n \n-iD8DBQBF0lGqwMbZpPMRm5oRAuRiAJ9ohBLd7s2kqjkKlq1qqC57SbnmzQCdG4ui\n-nLE/L9aUXdWeTFPron96DLA=\n-=2E+0\n------END PGP SIGNATURE-----\n+GIT 1.5.0\n ------------------------------------------------\n \n See the linkgit:git-tag[1] command to learn how to create and verify tag\n@@ -3702,9 +3704,9 @@ A tree can be created with linkgit:git-write-tree[1] and its data can be\n accessed by linkgit:git-ls-tree[1].  Two trees can be compared with\n linkgit:git-diff-tree[1].\n \n-A tag is created with linkgit:git-mktag[1], and the signature can be\n-verified by linkgit:git-verify-tag[1], though it is normally simpler to\n-use linkgit:git-tag[1] for both.\n+A tag is created with linkgit:git-mktag[1], and the cryptographic\n+signature can be verified by linkgit:git-verify-tag[1], though it is\n+normally simpler to use linkgit:git-tag[1] for both.\n \n [[the-workflow]]\n === The Workflow\n-- \n2.20.1\n\n"},{"id":"423921","messageId":"94624d84-be7e-016b-50f2-90a4c423be42@gmail.com","threadId":"55646","inReplyTo":"c454bcc4c3c5de1a17c63461c6091689098c75b9.1620454449.git.dwh@linuxprogrammer.org","subject":"Re: [RFC PATCH v1 1/1] Modifies documentation for universal cryptographic signing","fromName":"Bagas Sanjaya","fromEmail":"bagasdotme@gmail.com","sentAt":"2021-05-08T07:52:27Z","receivedAt":"2021-05-08T07:52:35Z","isPatch":true,"sender":{"key":"bagasdotme@gmail.com","avatar":"https://avatars.githubusercontent.com/u/40219486?v=4"},"body":"On 08/05/21 13.18, Dave Huseby wrote:\n> +In mergtags, the whole signed tag object is stored in the field name\n\nOops, s/mergtags/mergetags/\n\n> +The `sign` field is very similar to the old `gpgsig` field in commits. The data\n> +is can be multi-line with subsequent lines starting with spaces to mark them as\n> +additional data. The only difference is that the `sign` field stores signatures\n> +with newlines and carriage returns escaped because whitespace is significate in\n\nOops, s/significate/significant/\n\n-- \nAn old man doll... just what I always wanted! - Clara\n"},{"id":"423950","messageId":"YJcp3ZkZOfU+EMym@camp.crustytoothpaste.net","threadId":"55646","inReplyTo":"c454bcc4c3c5de1a17c63461c6091689098c75b9.1620454449.git.dwh@linuxprogrammer.org","subject":"Re: [RFC PATCH v1 1/1] Modifies documentation for universal cryptographic signing","fromName":"brian m. carlson","fromEmail":"sandals@crustytoothpaste.net","sentAt":"2021-05-09T00:16:29Z","receivedAt":"2021-05-09T00:17:08Z","isPatch":true,"sender":{"key":"sandals@crustytoothpaste.net","avatar":"https://avatars.githubusercontent.com/u/497054?v=4"},"body":"On 2021-05-08 at 06:18:23, Dave Huseby wrote:\n> Signed-off-by: Dave Huseby <dwh@linuxprogrammer.org>\n\nYou definitely need a commit message here explaining your approach and\njustifying it.  I'm not saying that your approach is bad, but people\ngenerally read the commit message to help understand and review the\ncommit, and we will want to know why you've made the decisions you've\nmade here and rejected other solutions, and the commit message will\nhopefully explain that to us.\n\n>  Signed Commits\n>  ~~~~~~~~~~~~~~\n> -We add a new field \"gpgsig-sha256\" to the commit object format to allow\n> -signing commits without relying on SHA-1. It is similar to the\n> -existing \"gpgsig\" field. Its signed payload is the SHA-256 content of the\n> -commit object with any \"gpgsig\" and \"gpgsig-sha256\" fields removed.\n> +We use the new signature format whenever signing commits without relying\n> +on SHA-1. The new format adds a 'signtype' field, zero or more 'signoption'\n> +fields, and one 'sign' field to commit objects. This allows for the 'gpgsig'\n> +field to coexist if needed.\n> \n>  This means commits can be signed\n> \n>  1. using SHA-1 only, as in existing signed commit objects\n> -2. using both SHA-1 and SHA-256, by using both gpgsig-sha256 and gpgsig\n> -   fields.\n> -3. using only SHA-256, by only using the gpgsig-sha256 field.\n> +2. using both SHA-1 and SHA-256, by using both gpgsig and the V2 format.\n> +3. using only SHA-256, by only using the V2 format.\n\nSHA-256 repositories already exist and already use this format.  You\ncannot change it now, since doing so will needlessly break commits.\nJust because they are experimental doesn't mean we should break\ncompatibility needlessly.\n\n>  Old versions of \"git verify-commit\" can verify the gpgsig signature in\n>  cases (1) and (2) without modifications and view case (3) as an\n> @@ -427,17 +426,16 @@ ordinary unsigned commit.\n>  Signed Tags\n>  ~~~~~~~~~~~\n> -We add a new field \"gpgsig-sha256\" to the tag object format to allow\n> -signing tags without relying on SHA-1. Its signed payload is the\n> -SHA-256 content of the tag with its gpgsig-sha256 field and \"-----BEGIN PGP\n> -SIGNATURE-----\" delimited in-body signature removed.\n> +We use the new signature format whenever signing tags without relying\n> +on SHA-1. The new format adds a 'signtype' field, zero or more 'signoption'\n> +fields, and one 'sign' field to tag objects. This allows for the in-body\n> +SHA-1 signature to coexist if needed.\n> \n>  This means tags can be signed\n> \n>  1. using SHA-1 only, as in existing signed tag objects\n> -2. using both SHA-1 and SHA-256, by using gpgsig-sha256 and an in-body\n> -   signature.\n> -3. using only SHA-256, by only using the gpgsig-sha256 field.\n> +2. using both SHA-1 and SHA-256, by using both gpgsig and the V2 format.\n> +3. using only SHA-256, by only using the V2 format.\n\nThe same thing here.  This is currently out of date; we use signed tags\nfor the same algorithm (that is, for the SHA-1 signature of a SHA-1\nobject and for the SHA-256 signature of a SHA-256 object) and fields for\nthe other.\n\n> +Version 2 Format\n> +----------------\n> +\n> +The goals of the version 2 format are as follows:\n> +\n> +- Backwards Compatible with version 1 without any intervention.\n> +- Eliminate signature-format-specific string matching for detecting/parsing\n> +  version 2 signatures.\n> +- Use fields for storing signatures in all objects and transactions.\n> +- Have a field that identifies the signature format.\n> +- Have fields that store options required by the verification tool.\n> +- Store signature data verbatim as created with the signing tool with escaped\n> +  newlines and carriage returns.\n\nWe probably need to define what happens if both a v1 and v2 signature\noccur.  Probably the commit is invalid and should be rejected.\n\n> +Fields\n> +~~~~~~\n> +\n> +The version 2 format uses three new fields listed below:\n> +\n> +- signtype <signature format name>\n> +- signoption <token> [= <value>]\n> +- sign <multiline signature data>\n> +\n> +A complete signature must include exactly one `signtype` field, zero or more\n> +`signoption` fields and one `sign` field.\n\nThis is going to be a problem.  We want to dual-sign objects over both\ntheir SHA-1 and SHA-256 values.  We already have dual-signed objects in\nthe repository.\n\n> +The `signtype` field has a string value that identifies the type of signature\n> +that is stored in the object. This string is case-insensitive and is used to\n> +identify which configuration settings are to used when verifying the signature.\n> +The corresponding configuration settings are in the config file as:\n> +'sign.<signType>.options.*'. The 'sign' field stores the text-encoded signature\n> +from the signing tool with any newlines and carriage returns escaped as '%0a'\n> +and '%0d' respectively. Whitespace is significant in digital signatures and\n> +the protocol for sending/receiving data to/from signing and verification tools\n> +requires that newlines and carriage returns are escaped. By storing the escaped\n> +version in the 'sign' field, we avoid extra processing and error-prone\n> +escaping.\n\nIs there a reason we can't use the indented block format currently used\nby gpgsig and friends?  Are there really formats that need to support\ncarriage returns in their signature?  If so, can we just specify those\nalgorithms will encode it with base64?\n\nAlso, it will be required to escape other values as well.  For example,\nif you encode things with %, then you must escape %.  Git will also not\nallow NUL bytes in commit objects, so if you want to encode arbitrary\nbinary data (which I would just do by requiring people to base64, but\nyou may not want to), you'll need to escape them as well.\n\n> +The introduction of the 'signoption' field is necessary for Git to remain\n> +agnostic to the tools used for signing and verification of cryptographic\n> +signatures. Some signign tools do not produce cryptographic signatures that\n> +include all of the data needed to verify the signature. A good example of this\n> +is the minisign tool (https://jedisct1.github.io/minisign/) which requires the\n> +public key to be supplied to the verification operation. In that case, the\n> +signing operation would return to Git a 'signoption' field along with the\n> +'signtype' and 'sign' fields to be stored in the Git object. When Git verifies\n> +the signature, it will parse the 'signoption' fields and send them to the\n> +verification tool as OPTION commands. In this case it will send the public key\n> +along with the signature for verification. This design allows for arbitrary\n> +options to be stored in the Git object by the signing tool that will get passed\n> +to the verification tool later without Git knowing or understanding any details\n> +of a particular signing tool.\n\nWhile I'd like to see us support minisign, I have concerns about\nembedding the public key in the signature.  First, that bloats commit\nobjects, and large commit objects can cause performance and scalability\nproblems.  Many things like partial clone implicitly assume that commits\nand tags are small.\n\nSecond, the goal is presumably to verify that the signature identifies\nsome relevant party, not just some arbitrary user.  As a consequence, I\nthink it's safe to assume that we have a way to acquire the public key\nof the trusted user whose signature we want to verify.\n\n> +The order in which OPTION commands are sent to the signing and verification\n> +tools is significant. OPTION commands that come later override OPTION commands\n> +that came earlier and had the same token name. Git always sends OPTION commands\n> +from the command line after the options from the config. In verification\n> +operations, Git sends the options from the signed object first, before the\n> +config and command line options. This ensures local control over option values.\n> +An example would be if the sign.openpgp.options.minTrustLevel config option is\n> +set to \"marginal\" and the command line `--sign-option minTrustLevel = full` is\n> +issued. Git would first send an OPTION command setting\n> +`minTrustLevel = marginal` from the config and then override that by later\n> +sending an OPTION command setting `minTrustLevel = full` from the command line.\n\nIt's a security problem to allow people to control verification\nparameters or command-line options.  The former allows users to validate\nsignatures using weak algorithms or reduced trust levels, and the latter\nmay allow arbitrary code execution.\n\nUnless this field is going to be used for some signature parameter other\nthan public keys or verification parameters, I'd rather we omit it.  If\nwe keep it, the allowed parameters must be strictly defined and\ndocumented per format and not allowed to contain arbitrary data.\n\nOverall, I'm generally positive on this approach, although I think it\nneeds some further refinements as I've mentioned above.  My preference\nis that we specifically document specific signature schemes and, if we\nkeep the options, which options are allowed.  For example, \"minisign\"\nand \"signify\" are compatible, and by specifying and documenting\nwell-known formats, we avoid the problem where people end up writing\ninvalid commits by typoing the name in their config.\n-- \nbrian m. carlson (he/him or they/them)\nHouston, Texas, US\n"}]}