Package: guix-patches;
Reported by: Ludovic Courtès <ludo <at> gnu.org>
Date: Mon, 5 Sep 2022 16:10:02 UTC
Severity: normal
Tags: patch, wontfix
Done: Ludovic Courtès <ludo <at> gnu.org>
Bug is archived. No further changes may be made.
View this message in rfc822 format
From: Ludovic Courtès <ludo <at> gnu.org> To: 57599 <at> debbugs.gnu.org Cc: Ludovic Courtès <ludo <at> gnu.org>, Zhu Zihao <all_but_last <at> 163.com>, 57576 <at> debbugs.gnu.org Subject: [bug#57599] [PATCH] openpgp: Add support for ECDSA with NIST curves. Date: Mon, 5 Sep 2022 18:09:29 +0200
Fixes <https://issues.guix.gnu.org/57576>. Reported by Zhu Zihao <all_but_last <at> 163.com>. * guix/openpgp.scm (verify-openpgp-signature): Add case for ecdsa. (get-signature): Likewise for PUBLIC-KEY-ECDSA. (get-public-key): Likewise. * tests/keys/secp384.pub, tests/keys/secp384.sec, tests/keys/secp521.pub, tests/keys/secp521.sec: New files. * Makefile.am (EXTRA_DIST): Add them. * tests/openpgp.scm (%secp384-key-id, %secp384-key-fingerprint) (%hello-signature/secp384/sha384) (%secp521-key-id, %secp521-key-fingerprint) (%hello-signature/secp521/sha521): New variables. * tests/openpgp.scm ("get-openpgp-detached-signature/ascii") ("verify-openpgp-signature, good signatures") ("verify-openpgp-signature, bad signature"): Check with the secp384 and secp521 curves. --- Makefile.am | 4 +++ guix/openpgp.scm | 41 +++++++++++++++++++++----- tests/keys/secp384.pub | 11 +++++++ tests/keys/secp384.sec | 12 ++++++++ tests/keys/secp521.pub | 13 +++++++++ tests/keys/secp521.sec | 14 +++++++++ tests/openpgp.scm | 66 +++++++++++++++++++++++++++++++++++------- 7 files changed, 143 insertions(+), 18 deletions(-) create mode 100644 tests/keys/secp384.pub create mode 100644 tests/keys/secp384.sec create mode 100644 tests/keys/secp521.pub create mode 100644 tests/keys/secp521.sec diff --git a/Makefile.am b/Makefile.am index a0c4e941c1..71c3bd4a98 100644 --- a/Makefile.am +++ b/Makefile.am @@ -702,6 +702,10 @@ EXTRA_DIST += \ tests/keys/ed25519-2.sec \ tests/keys/ed25519-3.pub \ tests/keys/ed25519-3.sec \ + tests/keys/secp384.pub \ + tests/keys/secp384.sec \ + tests/keys/secp521.pub \ + tests/keys/secp521.sec \ build-aux/config.rpath \ bootstrap \ doc/build.scm \ diff --git a/guix/openpgp.scm b/guix/openpgp.scm index 9de7feb644..b999c30474 100644 --- a/guix/openpgp.scm +++ b/guix/openpgp.scm @@ -1,6 +1,6 @@ ;; -*- mode: scheme; coding: utf-8 -*- ;; Copyright © 2010, 2012 Göran Weinholt <goran <at> weinholt.se> -;; Copyright © 2020 Ludovic Courtès <ludo <at> gnu.org> +;; Copyright © 2020, 2022 Ludovic Courtès <ludo <at> gnu.org> ;; Permission is hereby granted, free of charge, to any person obtaining a ;; copy of this software and associated documentation files (the "Software"), @@ -290,7 +290,7 @@ (define PUBLIC-KEY-RSA-SIGN-ONLY 3) (define PUBLIC-KEY-ELGAMAL-ENCRYPT-ONLY 16) (define PUBLIC-KEY-DSA 17) (define PUBLIC-KEY-ECDH 18) ;RFC-6637 -(define PUBLIC-KEY-ECDSA 19) ;RFC-6639 +(define PUBLIC-KEY-ECDSA 19) ;RFC-6637 (define PUBLIC-KEY-ELGAMAL 20) ;encrypt + sign (legacy) (define PUBLIC-KEY-EDDSA 22) ;"not yet assigned" says GPG @@ -298,6 +298,7 @@ (define (public-key-algorithm id) (cond ((= id PUBLIC-KEY-RSA) 'rsa) ((= id PUBLIC-KEY-DSA) 'dsa) ((= id PUBLIC-KEY-ELGAMAL-ENCRYPT-ONLY) 'elgamal) + ((= id PUBLIC-KEY-ECDSA) 'ecdsa) ((= id PUBLIC-KEY-EDDSA) 'eddsa) (else id))) @@ -564,10 +565,16 @@ (define (check key sig) ;; See "(gcrypt) Cryptographic Functions". (sexp->canonical-sexp (if (eq? key-type 'ecc) - `(data - (flags eddsa) - (hash-algo sha512) - (value ,hash)) + (match (openpgp-signature-public-key-algorithm sig) + ('eddsa + `(data + (flags eddsa) + (hash-algo sha512) + (value ,hash))) + ('ecdsa + `(data + (hash-algo ,(openpgp-signature-hash-algorithm sig)) + (value ,hash)))) `(data (flags ,(match key-type ('rsa 'pkcs1) @@ -615,7 +622,8 @@ (define (get-sig p pkalg) (string->canonical-sexp (format #f "(sig-val (dsa (r #~a#) (s #~a#)))" (->hex r) (->hex s))))) - ((= pkalg PUBLIC-KEY-EDDSA) + ((or (= pkalg PUBLIC-KEY-EDDSA) + (= pkalg PUBLIC-KEY-ECDSA)) (print "EdDSA signature") (let ((r (get-mpi/bytevector p)) (s (get-mpi/bytevector p))) @@ -630,7 +638,8 @@ (define (bytevector->hex bv) str))) (string->canonical-sexp - (format #f "(sig-val (eddsa (r #~a#) (s #~a#)))" + (format #f "(sig-val (~a (r #~a#) (s #~a#)))" + (public-key-algorithm pkalg) (bytevector->hex r) (bytevector->hex s))))) (else (list 'unsupported-algorithm @@ -886,6 +895,22 @@ (define curve curve (if (eq? curve 'Curve25519) 'djb-tweak 'eddsa) (->hex q))))) + ((= alg PUBLIC-KEY-ECDSA) + (print "Public ECDSA key") + (let* ((len (get-u8 p)) + (oid (bytevector->uint (get-bytevector-n p len))) + (q (get-mpi p))) + (define curve + ;; RFC 6637, Section 11. + (match oid + (#x2a8648ce3d030107 "NIST P-256") + (#x2b81040022 "NIST P-384") + (#x2b81040023 "NIST P-521"))) + + (string->canonical-sexp + (format #f "(public-key (ecc (curve \"~a\")(q #~a#)))" + curve + (->hex q))))) (else (list 'unsupported-algorithm ;FIXME: throw (public-key-algorithm alg) diff --git a/tests/keys/secp384.pub b/tests/keys/secp384.pub new file mode 100644 index 0000000000..b90cf504e2 --- /dev/null +++ b/tests/keys/secp384.pub @@ -0,0 +1,11 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mG8EYxYF9RMFK4EEACIDAwTHYxcyBiiPz4ZZIkmXnVu0Yv9DHGrnbdCR6U/RT1S4 +wszaHdsSEHlPwmy3WGgTubBDOuJODf5kV/HLL7QEPsOTkIsObK+prEJO3CGpRVim +a7nfVk2AH6D/GMkNacSXdwy0FTxleGFtcGxlQGV4YW1wbGUuY29tPoiwBBMTCQA4 +AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEzLZ9Sx8EBzgp+PzwLydGMf8+ +bFsFAmMWB+sACgkQLydGMf8+bFuD3gF/SMEDQP3Bvu0yb8KxE6j8lhOiKT186wwG +4hBsifRdEF+UHWEa7sx74tyc4R1B01FUAYC/4QqNup4EnPzQfSE3WyVvu+ja+xui +3vppYCpUjkHzkATsLzsN98/nkZ3q3YA8/lo= +=vIaC +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/keys/secp384.sec b/tests/keys/secp384.sec new file mode 100644 index 0000000000..ae296dd9a1 --- /dev/null +++ b/tests/keys/secp384.sec @@ -0,0 +1,12 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lKQEYxYF9RMFK4EEACIDAwTHYxcyBiiPz4ZZIkmXnVu0Yv9DHGrnbdCR6U/RT1S4 +wszaHdsSEHlPwmy3WGgTubBDOuJODf5kV/HLL7QEPsOTkIsObK+prEJO3CGpRVim +a7nfVk2AH6D/GMkNacSXdwwAAYC9iXZ9j+RWFB4rU103SCv6j68rS5Lmc7tHve9l +B5nri/AR+OEJ61q+w6w0XO5GBBUYLrQVPGV4YW1wbGVAZXhhbXBsZS5jb20+iLAE +ExMJADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTMtn1LHwQHOCn4/PAv +J0Yx/z5sWwUCYxYH6wAKCRAvJ0Yx/z5sW4PeAX9IwQNA/cG+7TJvwrETqPyWE6Ip +PXzrDAbiEGyJ9F0QX5QdYRruzHvi3JzhHUHTUVQBgL/hCo26ngSc/NB9ITdbJW+7 +6Nr7G6Le+mlgKlSOQfOQBOwvOw33z+eRnerdgDz+Wg== +=B1Nl +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/keys/secp521.pub b/tests/keys/secp521.pub new file mode 100644 index 0000000000..077e8e7df2 --- /dev/null +++ b/tests/keys/secp521.pub @@ -0,0 +1,13 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mJMEYxYamRMFK4EEACMEIwQB4EqA0zTAfhLeVjkNnzvTuSYs+TUlYdDaw9mYA7Gy +AiNvxr2F1hJi88Wxxr3YNGKx9s0yJ2Vl0dHlCLmlQAFc9MMACZKWZN68mqbYfSVf +qJxSG5F8qbF0+dGecwY+TjM4xdaUk4d0vD13/e+r/HLYNgwKrpO2SurNZX/isfkn +rvNSHPi0HTxleGFtcGxlLXNlY3A1MjFAZXhhbXBsZS5jb20+iNoEExMKAD4WIQQ7 +r36YQGm2cfPDEWnoSxOgtOevGwUCYxYamQIbAwUJA8JnAAULCQgHAgYVCgkICwIE +FgIDAQIeAQIXgAAKCRDoSxOgtOevG4GUAgkBN118FBDW896Iv+2U/29Fpfni4V6D +Vp6HTE5qAqmJUtKOOSxmDAmiJ4sinybTP4YCLQT9fmMQqrJSSY0d/hVg4fYCCQGD +Y6iRT8KPyxhlpsVVwdiUjOd4B5JUyJj0qOudY4yveyOl6c1bdxJALMbEHV4JREEE +1+ylYN1KRfpaQh42Zoms9Q== +=Nru3 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/keys/secp521.sec b/tests/keys/secp521.sec new file mode 100644 index 0000000000..663dbeaa3c --- /dev/null +++ b/tests/keys/secp521.sec @@ -0,0 +1,14 @@ +-----BEGIN PGP PRIVATE KEY BLOCK----- + +lNoEYxYamRMFK4EEACMEIwQB4EqA0zTAfhLeVjkNnzvTuSYs+TUlYdDaw9mYA7Gy +AiNvxr2F1hJi88Wxxr3YNGKx9s0yJ2Vl0dHlCLmlQAFc9MMACZKWZN68mqbYfSVf +qJxSG5F8qbF0+dGecwY+TjM4xdaUk4d0vD13/e+r/HLYNgwKrpO2SurNZX/isfkn +rvNSHPgAAgkBRPFeWJ3ZROkkbV7/dF8Z4LN6hlrSHWWS2sZmKxZprQy/j48eqWZz +6eY9IvDxfP9ATpfummdgrjexVqA3o3/wr00h/LQdPGV4YW1wbGUtc2VjcDUyMUBl +eGFtcGxlLmNvbT6I0gQTEwoAOAIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgBYh +BDuvfphAabZx88MRaehLE6C0568bBQJjFhroAAoJEOhLE6C0568bQl0CCNYMV2uF +6LA4GF8RchFQee4ZZo8aquEQ7t7a6NDBc1TbVkGLR+TWxkomEytp5EUoEEU2cNtg +TWRvti3aZvTbEMvdAgijAGTSiO3q5kjprGu1C35oc2JWj0q66XzHEJ0aEiTMQNrz +sJReJPQRmMnBTtzjJCmNPws/VYSEs26m36QCqePtwQ== +=/mn1 +-----END PGP PRIVATE KEY BLOCK----- diff --git a/tests/openpgp.scm b/tests/openpgp.scm index 1f20466772..68439f7485 100644 --- a/tests/openpgp.scm +++ b/tests/openpgp.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2020 Ludovic Courtès <ludo <at> gnu.org> +;;; Copyright © 2020, 2022 Ludovic Courtès <ludo <at> gnu.org> ;;; ;;; This file is part of GNU Guix. ;;; @@ -63,7 +63,7 @@ (define %civodul-key-id #x090B11993D9AEBB5) ;civodul.pub #| Test keys in ./tests/keys. They were generated in a container along these lines: - guix environment -CP --ad-hoc gnupg pinentry coreutils + guix shell -CP-hoc gnupg pinentry coreutils then, within the container: mkdir ~/.gnupg && chmod -R og-rwx ~/.gnupg gpg --batch --passphrase '' --quick-gen-key '<example <at> example.com>' ed25519 @@ -75,6 +75,8 @@ (define %civodul-key-id #x090B11993D9AEBB5) ;civodul.pub (define %rsa-key-id #xAE25DA2A70DEED59) ;rsa.pub (define %dsa-key-id #x587918047BE8BD2C) ;dsa.pub (define %ed25519-key-id #x771F49CBFAAE072D) ;ed25519.pub +(define %secp384-key-id #x2F274631FF3E6C5B) ;secp384.pub +(define %secp521-key-id #xE84B13A0B4E7AF1B) ;secp521.pub (define %rsa-key-fingerprint (base16-string->bytevector @@ -85,6 +87,12 @@ (define %dsa-key-fingerprint (define %ed25519-key-fingerprint (base16-string->bytevector (string-downcase "44D31E21AF7138F9B632280A771F49CBFAAE072D"))) +(define %secp384-key-fingerprint + (base16-string->bytevector + (string-downcase "CCB67D4B1F04073829F8FCF02F274631FF3E6C5B"))) +(define %secp521-key-fingerprint + (base16-string->bytevector + (string-downcase "3BAF7E984069B671F3C31169E84B13A0B4E7AF1B"))) ;;; The following are detached signatures created commands like: @@ -148,6 +156,28 @@ (define %hello-signature/ed25519/sha1 ;digest-algo: sha1 =AE4G -----END PGP SIGNATURE-----") +(define %hello-signature/secp384/sha384 ;digest-algo: sha384 + "\ +-----BEGIN PGP SIGNATURE----- + +iJUEABMJAB0WIQTMtn1LHwQHOCn4/PAvJ0Yx/z5sWwUCYxYIKAAKCRAvJ0Yx/z5s +WxD2AX0QMeTHLJvJxRKTBP8O9kGMY9Nz0kzRBO0OJG2gYyxu9sZ+NAEQF01jAOXl +ApL2zVkBgLUyyleJtR24LKxK73waLJb51TA29NXJJZ2fiRZ50u/lNfrFR3PYnK7/ +gvSkL3Ldzw== +=+7h3 +-----END PGP SIGNATURE-----") + +(define %hello-signature/secp521/sha512 + "\ +-----BEGIN PGP SIGNATURE----- + +iLcEABMKAB0WIQQ7r36YQGm2cfPDEWnoSxOgtOevGwUCYxYb+wAKCRDoSxOgtOev +G+ByAgdwIBTnCtzo+lFuahhMMScXZZeTH055IOhTsXmptZaE3MaazTsUw3en8C9i +EWiy/GDQKaJEZMP3dwN1+3tNTl/NUAIIiV/BFly9Ha/cYJG+p3LG24JoHVfJx04q +LfSXejfMIvu33h8wjMA2tRQSlqdDylMWKThJgp6GH6svp+Zr4z+Smnw= +=1zW0 +-----END PGP SIGNATURE-----") + (test-begin "openpgp") @@ -193,7 +223,9 @@ (define %hello-signature/ed25519/sha1 ;digest-algo: sha1 `(,%rsa-key-id ,%rsa-key-fingerprint rsa sha256) `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha256) `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha512) - `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha1)) + `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha1) + `(,%secp384-key-id ,%secp384-key-fingerprint ecdsa sha384) + `(,%secp521-key-id ,%secp521-key-fingerprint ecdsa sha512)) (map (lambda (str) (let ((signature (get-openpgp-detached-signature/ascii (open-input-string str)))) @@ -205,7 +237,9 @@ (define %hello-signature/ed25519/sha1 ;digest-algo: sha1 %hello-signature/rsa %hello-signature/ed25519/sha256 %hello-signature/ed25519/sha512 - %hello-signature/ed25519/sha1))) + %hello-signature/ed25519/sha1 + %hello-signature/secp384/sha384 + %hello-signature/secp521/sha512))) (test-equal "verify-openpgp-signature, missing key" `(missing-key ,%rsa-key-fingerprint) @@ -221,7 +255,9 @@ (define %hello-signature/ed25519/sha1 ;digest-algo: sha1 (good-signature ,%dsa-key-id) (good-signature ,%ed25519-key-id) (good-signature ,%ed25519-key-id) - (good-signature ,%ed25519-key-id)) + (good-signature ,%ed25519-key-id) + (good-signature ,%secp384-key-id) + (good-signature ,%secp521-key-id)) (map (lambda (key signature) (let* ((key (search-path %load-path key)) (keyring (get-openpgp-keyring @@ -235,18 +271,24 @@ (define %hello-signature/ed25519/sha1 ;digest-algo: sha1 (list "tests/keys/rsa.pub" "tests/keys/dsa.pub" "tests/keys/ed25519.pub" "tests/keys/ed25519.pub" - "tests/keys/ed25519.pub") + "tests/keys/ed25519.pub" + "tests/keys/secp384.pub" + "tests/keys/secp521.pub") (list %hello-signature/rsa %hello-signature/dsa %hello-signature/ed25519/sha256 %hello-signature/ed25519/sha512 - %hello-signature/ed25519/sha1))) + %hello-signature/ed25519/sha1 + %hello-signature/secp384/sha384 + %hello-signature/secp521/sha512))) (test-equal "verify-openpgp-signature, bad signature" `((bad-signature ,%rsa-key-id) (bad-signature ,%dsa-key-id) (bad-signature ,%ed25519-key-id) (bad-signature ,%ed25519-key-id) - (bad-signature ,%ed25519-key-id)) + (bad-signature ,%ed25519-key-id) + (bad-signature ,%secp384-key-id) + (bad-signature ,%secp521-key-id)) (let ((keyring (fold (lambda (key keyring) (let ((key (search-path %load-path key))) (get-openpgp-keyring @@ -256,7 +298,9 @@ (define %hello-signature/ed25519/sha1 ;digest-algo: sha1 %empty-keyring '("tests/keys/rsa.pub" "tests/keys/dsa.pub" "tests/keys/ed25519.pub" "tests/keys/ed25519.pub" - "tests/keys/ed25519.pub")))) + "tests/keys/ed25519.pub" + "tests/keys/secp384.pub" + "tests/keys/secp521.pub")))) (map (lambda (signature) (let ((signature (string->openpgp-packet signature))) (let-values (((status key) @@ -266,6 +310,8 @@ (define %hello-signature/ed25519/sha1 ;digest-algo: sha1 (list %hello-signature/rsa %hello-signature/dsa %hello-signature/ed25519/sha256 %hello-signature/ed25519/sha512 - %hello-signature/ed25519/sha1)))) + %hello-signature/ed25519/sha1 + %hello-signature/secp384/sha384 + %hello-signature/secp521/sha512)))) (test-end "openpgp") base-commit: aae98c297214f87eb45302863adb021078c41a6f -- 2.37.2
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.