diff options
| -rw-r--r-- | guix/openpgp.scm | 44 | ||||
| -rw-r--r-- | tests/openpgp.scm | 22 |
2 files changed, 56 insertions, 10 deletions
diff --git a/guix/openpgp.scm b/guix/openpgp.scm index bfdbe4b61b7..77a75373df2 100644 --- a/guix/openpgp.scm +++ b/guix/openpgp.scm | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | 33 | ||
| 34 | openpgp-signature? | 34 | openpgp-signature? |
| 35 | openpgp-signature-issuer | 35 | openpgp-signature-issuer |
| 36 | openpgp-signature-issuer-fingerprint | ||
| 36 | openpgp-signature-public-key-algorithm | 37 | openpgp-signature-public-key-algorithm |
| 37 | openpgp-signature-hash-algorithm | 38 | openpgp-signature-hash-algorithm |
| 38 | openpgp-signature-creation-time | 39 | openpgp-signature-creation-time |
| @@ -345,7 +346,6 @@ hexadecimal format for fingerprints." | |||
| 345 | ;; 12 = Revocation Key | 346 | ;; 12 = Revocation Key |
| 346 | 347 | ||
| 347 | (define SUBPACKET-ISSUER 16) | 348 | (define SUBPACKET-ISSUER 16) |
| 348 | ;; TODO: hashed SUBPACKET-ISSUER-FINGERPRINT-V4 | ||
| 349 | (define SUBPACKET-NOTATION-DATA 20) | 349 | (define SUBPACKET-NOTATION-DATA 20) |
| 350 | (define SUBPACKET-PREFERRED-HASH-ALGORITHMS 21) | 350 | (define SUBPACKET-PREFERRED-HASH-ALGORITHMS 21) |
| 351 | (define SUBPACKET-PREFERRED-COMPRESSION-ALGORITHMS 22) | 351 | (define SUBPACKET-PREFERRED-COMPRESSION-ALGORITHMS 22) |
| @@ -358,8 +358,8 @@ hexadecimal format for fingerprints." | |||
| 358 | (define SUBPACKET-REASON-FOR-REVOCATION 29) | 358 | (define SUBPACKET-REASON-FOR-REVOCATION 29) |
| 359 | (define SUBPACKET-FEATURES 30) | 359 | (define SUBPACKET-FEATURES 30) |
| 360 | ;; 31 = Signature Target | 360 | ;; 31 = Signature Target |
| 361 | |||
| 362 | (define SUBPACKET-EMBEDDED-SIGNATURE 32) | 361 | (define SUBPACKET-EMBEDDED-SIGNATURE 32) |
| 362 | (define SUBPACKET-ISSUER-FINGERPRINT 33) ;defined in RFC4880bis | ||
| 363 | 363 | ||
| 364 | (define SIGNATURE-BINARY #x00) | 364 | (define SIGNATURE-BINARY #x00) |
| 365 | (define SIGNATURE-TEXT #x01) | 365 | (define SIGNATURE-TEXT #x01) |
| @@ -486,6 +486,13 @@ hexadecimal format for fingerprints." | |||
| 486 | ;; XXX: is the issuer always in the unhashed subpackets? | 486 | ;; XXX: is the issuer always in the unhashed subpackets? |
| 487 | (else #f))) | 487 | (else #f))) |
| 488 | 488 | ||
| 489 | (define (openpgp-signature-issuer-fingerprint sig) | ||
| 490 | "When it's available, return the fingerprint, a bytevector, or the issuer of | ||
| 491 | SIG. Otherwise, return #f." | ||
| 492 | (or (assoc-ref (openpgp-signature-hashed-subpackets sig) 'issuer-fingerprint) | ||
| 493 | (assoc-ref (openpgp-signature-unhashed-subpackets sig) | ||
| 494 | 'issuer-fingerprint))) | ||
| 495 | |||
| 489 | (define (openpgp-signature-creation-time sig) | 496 | (define (openpgp-signature-creation-time sig) |
| 490 | (cond ((assq 'signature-ctime (openpgp-signature-hashed-subpackets sig)) | 497 | (cond ((assq 'signature-ctime (openpgp-signature-hashed-subpackets sig)) |
| 491 | => (lambda (x) (unixtime (cdr x)))) | 498 | => (lambda (x) (unixtime (cdr x)))) |
| @@ -578,6 +585,14 @@ the issuer's OpenPGP public key extracted from KEYRING." | |||
| 578 | (values 'missing-key issuer)))) | 585 | (values 'missing-key issuer)))) |
| 579 | (values 'unsupported-signature sig))) | 586 | (values 'unsupported-signature sig))) |
| 580 | 587 | ||
| 588 | (define (key-id-matches-fingerprint? key-id fingerprint) | ||
| 589 | "Return true if KEY-ID, a number, corresponds to the low 8 bytes of | ||
| 590 | FINGERPRINT, a bytevector." | ||
| 591 | (let* ((len (bytevector-length fingerprint)) | ||
| 592 | (low (make-bytevector 8))) | ||
| 593 | (bytevector-copy! fingerprint (- len 8) low 0 8) | ||
| 594 | (= (bytevector->uint low) key-id))) | ||
| 595 | |||
| 581 | (define (get-signature p) | 596 | (define (get-signature p) |
| 582 | (define (->hex n) | 597 | (define (->hex n) |
| 583 | (string-hex-pad (number->string n 16))) | 598 | (string-hex-pad (number->string n 16))) |
| @@ -662,14 +677,26 @@ the issuer's OpenPGP public key extracted from KEYRING." | |||
| 662 | ;; Errata ID: 2214. | 677 | ;; Errata ID: 2214. |
| 663 | (integers->bytevector u8 #x04 | 678 | (integers->bytevector u8 #x04 |
| 664 | u8 #xff | 679 | u8 #xff |
| 665 | u32 (+ 6 subpacket-len))))) | 680 | u32 (+ 6 subpacket-len)))) |
| 681 | (unhashed-subpackets | ||
| 682 | (parse-subpackets unhashed-subpackets)) | ||
| 683 | (hashed-subpackets (parse-subpackets hashed-subpackets)) | ||
| 684 | (subpackets (append hashed-subpackets | ||
| 685 | unhashed-subpackets)) | ||
| 686 | (issuer-key-id (assoc-ref subpackets 'issuer)) | ||
| 687 | (issuer (assoc-ref subpackets | ||
| 688 | 'issuer-fingerprint))) | ||
| 689 | (unless (or (not issuer) (not issuer-key-id) | ||
| 690 | (key-id-matches-fingerprint? issuer-key-id issuer)) | ||
| 691 | (error "issuer key id does not match fingerprint" issuer)) | ||
| 692 | |||
| 666 | (make-openpgp-signature version type | 693 | (make-openpgp-signature version type |
| 667 | (public-key-algorithm pkalg) | 694 | (public-key-algorithm pkalg) |
| 668 | (openpgp-hash-algorithm halg) | 695 | (openpgp-hash-algorithm halg) |
| 669 | hashl16 | 696 | hashl16 |
| 670 | append-data | 697 | append-data |
| 671 | (parse-subpackets hashed-subpackets) | 698 | hashed-subpackets |
| 672 | (parse-subpackets unhashed-subpackets) | 699 | unhashed-subpackets |
| 673 | value))))) | 700 | value))))) |
| 674 | (else | 701 | (else |
| 675 | (print "Unsupported signature version: " version) | 702 | (print "Unsupported signature version: " version) |
| @@ -701,6 +728,13 @@ the issuer's OpenPGP public key extracted from KEYRING." | |||
| 701 | ((= type SUBPACKET-ISSUER) | 728 | ((= type SUBPACKET-ISSUER) |
| 702 | (cons 'issuer | 729 | (cons 'issuer |
| 703 | (bytevector-u64-ref data 0 (endianness big)))) | 730 | (bytevector-u64-ref data 0 (endianness big)))) |
| 731 | ((= type SUBPACKET-ISSUER-FINGERPRINT) ;v4+ only, RFC4880bis | ||
| 732 | (cons 'issuer-fingerprint | ||
| 733 | (let* ((version (bytevector-u8-ref data 0)) | ||
| 734 | (len (match version (4 20) (5 32)) ) | ||
| 735 | (fingerprint (make-bytevector len))) | ||
| 736 | (bytevector-copy! data 1 fingerprint 0 len) | ||
| 737 | fingerprint))) | ||
| 704 | ((= type SUBPACKET-NOTATION-DATA) | 738 | ((= type SUBPACKET-NOTATION-DATA) |
| 705 | (let ((p (open-bytevector-input-port data))) | 739 | (let ((p (open-bytevector-input-port data))) |
| 706 | (let-values (((f1 nlen vlen) | 740 | (let-values (((f1 nlen vlen) |
diff --git a/tests/openpgp.scm b/tests/openpgp.scm index 8a3c7bbeb7d..20d65171fd8 100644 --- a/tests/openpgp.scm +++ b/tests/openpgp.scm | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | (define-module (tests-openpgp) | 19 | (define-module (tests-openpgp) |
| 20 | #:use-module (guix openpgp) | 20 | #:use-module (guix openpgp) |
| 21 | #:use-module (gcrypt base16) | ||
| 21 | #:use-module (gcrypt hash) | 22 | #:use-module (gcrypt hash) |
| 22 | #:use-module (gcrypt pk-crypto) | 23 | #:use-module (gcrypt pk-crypto) |
| 23 | #:use-module (ice-9 binary-ports) | 24 | #:use-module (ice-9 binary-ports) |
| @@ -65,6 +66,16 @@ vBSFjNSiVHsuAA== | |||
| 65 | (define %dsa-key-id #x587918047BE8BD2C) ;dsa.key | 66 | (define %dsa-key-id #x587918047BE8BD2C) ;dsa.key |
| 66 | (define %ed25519-key-id #x771F49CBFAAE072D) ;ed25519.key | 67 | (define %ed25519-key-id #x771F49CBFAAE072D) ;ed25519.key |
| 67 | 68 | ||
| 69 | (define %rsa-key-fingerprint | ||
| 70 | (base16-string->bytevector | ||
| 71 | (string-downcase "385F86CFC86B665A5C165E6BAE25DA2A70DEED59"))) | ||
| 72 | (define %dsa-key-fingerprint | ||
| 73 | (base16-string->bytevector | ||
| 74 | (string-downcase "2884A980422330A4F33DD97F587918047BE8BD2C"))) | ||
| 75 | (define %ed25519-key-fingerprint | ||
| 76 | (base16-string->bytevector | ||
| 77 | (string-downcase "44D31E21AF7138F9B632280A771F49CBFAAE072D"))) | ||
| 78 | |||
| 68 | 79 | ||
| 69 | ;;; The following are detached signatures created commands like: | 80 | ;;; The following are detached signatures created commands like: |
| 70 | ;;; echo 'Hello!' | gpg -sba --digest-algo sha512 | 81 | ;;; echo 'Hello!' | gpg -sba --digest-algo sha512 |
| @@ -160,15 +171,16 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0= | |||
| 160 | "Ludovic Courtès <ludo@gnu.org>")))))) | 171 | "Ludovic Courtès <ludo@gnu.org>")))))) |
| 161 | 172 | ||
| 162 | (test-equal "get-openpgp-detached-signature/ascii" | 173 | (test-equal "get-openpgp-detached-signature/ascii" |
| 163 | (list `(,%dsa-key-id dsa sha256) | 174 | (list `(,%dsa-key-id ,%dsa-key-fingerprint dsa sha256) |
| 164 | `(,%rsa-key-id rsa sha256) | 175 | `(,%rsa-key-id ,%rsa-key-fingerprint rsa sha256) |
| 165 | `(,%ed25519-key-id eddsa sha256) | 176 | `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha256) |
| 166 | `(,%ed25519-key-id eddsa sha512) | 177 | `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha512) |
| 167 | `(,%ed25519-key-id eddsa sha1)) | 178 | `(,%ed25519-key-id ,%ed25519-key-fingerprint eddsa sha1)) |
| 168 | (map (lambda (str) | 179 | (map (lambda (str) |
| 169 | (let ((signature (get-openpgp-detached-signature/ascii | 180 | (let ((signature (get-openpgp-detached-signature/ascii |
| 170 | (open-input-string str)))) | 181 | (open-input-string str)))) |
| 171 | (list (openpgp-signature-issuer signature) | 182 | (list (openpgp-signature-issuer signature) |
| 183 | (openpgp-signature-issuer-fingerprint signature) | ||
| 172 | (openpgp-signature-public-key-algorithm signature) | 184 | (openpgp-signature-public-key-algorithm signature) |
| 173 | (openpgp-signature-hash-algorithm signature)))) | 185 | (openpgp-signature-hash-algorithm signature)))) |
| 174 | (list %hello-signature/dsa | 186 | (list %hello-signature/dsa |
