diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2020-04-26 23:20:26 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2020-05-04 09:56:12 +0200 |
| commit | efe1f0122c61b8932671d07419f0200c170a994e (patch) | |
| tree | 970bd488de86bc1009dabc3c64e6d59f7ceeb5c5 | |
| parent | 7b2b3a13cc2d9b043f37b2e7ba0f147c08de8fad (diff) | |
openpgp: Add 'lookup-key-by-fingerprint'.
* guix/openpgp.scm (<openpgp-keyring>)[table]: Rename to...
[ids]: ... this.
[fingerprints]: New field.
(keyring-insert, lookup-key-by-fingerprint): New procedures.
(%empty-keyring): Adjust.
(get-openpgp-keyring): Manipulate KEYRING instead of its vhash, use
'keyring-insert'.
* tests/openpgp.scm ("get-openpgp-keyring"): Test
'lookup-key-by-fingerprint'.
| -rw-r--r-- | guix/openpgp.scm | 43 | ||||
| -rw-r--r-- | tests/openpgp.scm | 16 |
2 files changed, 40 insertions, 19 deletions
diff --git a/guix/openpgp.scm b/guix/openpgp.scm index 3b11998c112..8479f8a1682 100644 --- a/guix/openpgp.scm +++ b/guix/openpgp.scm | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | openpgp-keyring? | 52 | openpgp-keyring? |
| 53 | %empty-keyring | 53 | %empty-keyring |
| 54 | lookup-key-by-id | 54 | lookup-key-by-id |
| 55 | lookup-key-by-fingerprint | ||
| 55 | get-openpgp-keyring | 56 | get-openpgp-keyring |
| 56 | 57 | ||
| 57 | read-radix-64) | 58 | read-radix-64) |
| @@ -912,14 +913,32 @@ FINGERPRINT, a bytevector." | |||
| 912 | ;;; Keyring management | 913 | ;;; Keyring management |
| 913 | 914 | ||
| 914 | (define-record-type <openpgp-keyring> | 915 | (define-record-type <openpgp-keyring> |
| 915 | (openpgp-keyring table) | 916 | (openpgp-keyring ids fingerprints) |
| 916 | openpgp-keyring? | 917 | openpgp-keyring? |
| 917 | (table openpgp-keyring-table)) ;vhash mapping key id to packets | 918 | (ids openpgp-keyring-ids) ;vhash mapping key id to packets |
| 919 | (fingerprints openpgp-keyring-fingerprints)) ;mapping fingerprint to packets | ||
| 920 | |||
| 921 | (define* (keyring-insert key keyring #:optional (packets (list key))) | ||
| 922 | "Insert the KEY/PACKETS association into KEYRING and return the resulting | ||
| 923 | keyring. PACKETS typically contains KEY, an <openpgp-public-key>, alongside | ||
| 924 | with additional <openpgp-public-key> records for sub-keys, <openpgp-user-id> | ||
| 925 | records, and so on." | ||
| 926 | (openpgp-keyring (vhash-consv (openpgp-public-key-id key) packets | ||
| 927 | (openpgp-keyring-ids keyring)) | ||
| 928 | (vhash-cons (openpgp-public-key-fingerprint key) packets | ||
| 929 | (openpgp-keyring-fingerprints keyring)))) | ||
| 918 | 930 | ||
| 919 | (define (lookup-key-by-id keyring id) | 931 | (define (lookup-key-by-id keyring id) |
| 920 | "Return a list of packets for the key with ID in KEYRING, or #f if ID could | 932 | "Return a list of packets for the key with ID in KEYRING, or #f if ID could |
| 921 | not be found. ID must be the 64-bit key ID of the key, an integer." | 933 | not be found. ID must be the 64-bit key ID of the key, an integer." |
| 922 | (match (vhash-assv id (openpgp-keyring-table keyring)) | 934 | (match (vhash-assv id (openpgp-keyring-ids keyring)) |
| 935 | ((_ . lst) lst) | ||
| 936 | (#f '()))) | ||
| 937 | |||
| 938 | (define (lookup-key-by-fingerprint keyring fingerprint) | ||
| 939 | "Return a list of packets for the key with FINGERPRINT in KEYRING, or #f if | ||
| 940 | FINGERPRINT could not be found. FINGERPRINT must be a bytevector." | ||
| 941 | (match (vhash-assoc fingerprint (openpgp-keyring-fingerprints keyring)) | ||
| 923 | ((_ . lst) lst) | 942 | ((_ . lst) lst) |
| 924 | (#f '()))) | 943 | (#f '()))) |
| 925 | 944 | ||
| @@ -928,7 +947,7 @@ not be found. ID must be the 64-bit key ID of the key, an integer." | |||
| 928 | 947 | ||
| 929 | (define %empty-keyring | 948 | (define %empty-keyring |
| 930 | ;; The empty keyring. | 949 | ;; The empty keyring. |
| 931 | (openpgp-keyring vlist-null)) | 950 | (openpgp-keyring vlist-null vlist-null)) |
| 932 | 951 | ||
| 933 | (define* (get-openpgp-keyring port | 952 | (define* (get-openpgp-keyring port |
| 934 | #:optional (keyring %empty-keyring) | 953 | #:optional (keyring %empty-keyring) |
| @@ -939,15 +958,15 @@ complements KEYRING. LIMIT is the maximum number of keys to read, or -1 if | |||
| 939 | there is no limit." | 958 | there is no limit." |
| 940 | (let lp ((pkt (get-packet port)) | 959 | (let lp ((pkt (get-packet port)) |
| 941 | (limit limit) | 960 | (limit limit) |
| 942 | (keyring (openpgp-keyring-table keyring))) | 961 | (keyring keyring)) |
| 943 | (print "#;key " pkt) | 962 | (print "#;key " pkt) |
| 944 | (cond ((or (zero? limit) (eof-object? pkt)) | 963 | (cond ((or (zero? limit) (eof-object? pkt)) |
| 945 | (openpgp-keyring keyring)) | 964 | keyring) |
| 946 | ((openpgp-public-key-primary? pkt) | 965 | ((openpgp-public-key-primary? pkt) |
| 947 | ;; Read signatures, user id's, subkeys | 966 | ;; Read signatures, user id's, subkeys |
| 948 | (let lp* ((pkt (get-packet port)) | 967 | (let lp* ((pkt (get-packet port)) |
| 949 | (pkts (list pkt)) | 968 | (pkts (list pkt)) |
| 950 | (key-ids (list (openpgp-public-key-id pkt)))) | 969 | (keys (list pkt))) |
| 951 | (print "#;keydata " pkt) | 970 | (print "#;keydata " pkt) |
| 952 | (cond ((or (eof-object? pkt) | 971 | (cond ((or (eof-object? pkt) |
| 953 | (eq? pkt 'unsupported-public-key-version) | 972 | (eq? pkt 'unsupported-public-key-version) |
| @@ -957,13 +976,13 @@ there is no limit." | |||
| 957 | ;; packets. | 976 | ;; packets. |
| 958 | (lp pkt | 977 | (lp pkt |
| 959 | (- limit 1) | 978 | (- limit 1) |
| 960 | (fold (cute vhash-consv <> (reverse pkts) <>) | 979 | (fold (cute keyring-insert <> <> (reverse pkts)) |
| 961 | keyring key-ids))) | 980 | keyring keys))) |
| 962 | ((openpgp-public-key? pkt) ;subkey | 981 | ((openpgp-public-key? pkt) ;subkey |
| 963 | (lp* (get-packet port) (cons pkt pkts) | 982 | (lp* (get-packet port) (cons pkt pkts) |
| 964 | (cons (openpgp-public-key-id pkt) key-ids))) | 983 | (cons pkt keys))) |
| 965 | (else | 984 | (else |
| 966 | (lp* (get-packet port) (cons pkt pkts) key-ids))))) | 985 | (lp* (get-packet port) (cons pkt pkts) keys))))) |
| 967 | (else | 986 | (else |
| 968 | ;; Skip until there's a primary key. Ignore errors... | 987 | ;; Skip until there's a primary key. Ignore errors... |
| 969 | (lp (get-packet port) limit keyring))))) | 988 | (lp (get-packet port) limit keyring))))) |
diff --git a/tests/openpgp.scm b/tests/openpgp.scm index 1709167859d..eac2e88f747 100644 --- a/tests/openpgp.scm +++ b/tests/openpgp.scm | |||
| @@ -162,13 +162,15 @@ Pz7oopeN72xgggYUNT37ezqN3MeCqw0= | |||
| 162 | (call-with-input-file key read-radix-64))))) | 162 | (call-with-input-file key read-radix-64))))) |
| 163 | (match (lookup-key-by-id keyring %civodul-key-id) | 163 | (match (lookup-key-by-id keyring %civodul-key-id) |
| 164 | (((? openpgp-public-key? primary) packets ...) | 164 | (((? openpgp-public-key? primary) packets ...) |
| 165 | (and (= (openpgp-public-key-id primary) %civodul-key-id) | 165 | (let ((fingerprint (openpgp-public-key-fingerprint primary))) |
| 166 | (not (openpgp-public-key-subkey? primary)) | 166 | (and (= (openpgp-public-key-id primary) %civodul-key-id) |
| 167 | (string=? (openpgp-format-fingerprint | 167 | (not (openpgp-public-key-subkey? primary)) |
| 168 | (openpgp-public-key-fingerprint primary)) | 168 | (string=? (openpgp-format-fingerprint fingerprint) |
| 169 | %civodul-fingerprint) | 169 | %civodul-fingerprint) |
| 170 | (string=? (openpgp-user-id-value (find openpgp-user-id? packets)) | 170 | (string=? (openpgp-user-id-value (find openpgp-user-id? packets)) |
| 171 | "Ludovic Courtès <ludo@gnu.org>")))))) | 171 | "Ludovic Courtès <ludo@gnu.org>") |
| 172 | (equal? (lookup-key-by-id keyring %civodul-key-id) | ||
| 173 | (lookup-key-by-fingerprint keyring fingerprint)))))))) | ||
| 172 | 174 | ||
| 173 | (test-equal "get-openpgp-detached-signature/ascii" | 175 | (test-equal "get-openpgp-detached-signature/ascii" |
| 174 | (list `(,%dsa-key-id ,%dsa-key-fingerprint dsa sha256) | 176 | (list `(,%dsa-key-id ,%dsa-key-fingerprint dsa sha256) |
