Skip to content

Commit

Permalink
implement webkey gpg parsing to did
Browse files Browse the repository at this point in the history
  • Loading branch information
fairingrey committed Jan 13, 2022
1 parent 130cbee commit 7cfb6e7
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 23 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
/target
Cargo.lock

.vscode
17 changes: 10 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ description = "Core library for Verifiable Credentials and Decentralized Identif
repository = "https://github.com/spruceid/ssi/"
documentation = "https://docs.rs/ssi/"

exclude = [
"json-ld-api/*",
"json-ld-normalization/*",
]
exclude = ["json-ld-api/*", "json-ld-normalization/*"]

[features]
default = ["ring"]
http-did = ["hyper", "hyper-tls", "http", "percent-encoding", "tokio"]
libsecp256k1 = ["secp256k1"] # backward compatibility
libsecp256k1 = ["secp256k1"] # backward compatibility
secp256k1 = ["k256", "rand", "k256/keccak256"]
secp256r1 = ["p256", "rand"]
ripemd-160 = ["ripemd160", "secp256k1"]
Expand Down Expand Up @@ -58,7 +55,12 @@ lazy_static = "1.4"
combination = "0.1"
sha2 = { version = "0.9", optional = true }
sha2_old = { package = "sha2", version = "0.8" }
hyper = { version = "0.14", optional = true, features = ["server", "client", "http1", "stream"] }
hyper = { version = "0.14", optional = true, features = [
"server",
"client",
"http1",
"stream",
] }
hyper-tls = { version = "0.5", optional = true }
http = { version = "0.2", optional = true }
hex = "0.4"
Expand All @@ -77,6 +79,7 @@ p256 = { version = "0.8", optional = true, features = ["zeroize", "ecdsa"] }
ssi-contexts = { version = "0.1.2", path = "contexts/" }
ripemd160 = { version = "0.9", optional = true }
sshkeys = "0.3"
sequoia-openpgp = "1.7"
reqwest = { version = "0.11", features = ["json"] }
flate2 = "1.0"
bitvec = "0.20"
Expand Down Expand Up @@ -106,7 +109,7 @@ members = [
]

[dev-dependencies]
blake2 = "0.8" # for bbs doctest
blake2 = "0.8" # for bbs doctest
uuid = { version = "0.8", features = ["v4", "serde"] }
difference = "2.0"
did-method-key = { path = "./did-key" }
Expand Down
7 changes: 6 additions & 1 deletion did-webkey/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@ documentation = "https://docs.rs/did-webkey/"
p256 = ["ssi/p256"]

[dependencies]
ssi = { version = "0.3", path = "../", default-features = false }
ssi = { version = "0.3", path = "../", features = [
"rand",
"ring",
"p256",
], default-features = false }
async-trait = "0.1"
reqwest = { version = "0.11", features = ["json"] }
http = "0.2"
sequoia-openpgp = "1.7"
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
sshkeys = "0.3"
Expand Down
141 changes: 126 additions & 15 deletions did-webkey/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ use core::str::FromStr;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};

use openpgp::{
cert::prelude::*,
parse::{PacketParser, Parse},
serialize::SerializeInto,
};
use sequoia_openpgp as openpgp;
use sshkeys::PublicKeyKind;
use ssi::did::{DIDMethod, Document, VerificationMethod, VerificationMethodMap, DIDURL};
use ssi::did_resolve::{
Expand Down Expand Up @@ -39,11 +45,53 @@ impl FromStr for DIDWebKeyType {
}

fn parse_pubkeys_gpg(
_did: &str,
_bytes: Vec<u8>,
did: &str,
bytes: Vec<u8>,
) -> Result<(Vec<VerificationMethodMap>, Vec<DIDURL>), String> {
// TODO
Err(String::from("GPG Key Type Not Implemented"))
let mut did_urls = Vec::new();
let mut vm_maps = Vec::new();

let ppr = PacketParser::from_bytes(&bytes)
.map_err(|e| format!("Unable to parse GPG keyring: {}", e))?;
for certo in CertParser::from(ppr) {
let cert = certo.map_err(|e| format!("Error reading keyring: {}", e))?;
let (vm_map, did_url) = gpg_pk_to_vm(did, cert).map_err(|e| {
format!(
"Unable to convert GPG public key to verification method: {}",
e
)
})?;
vm_maps.push(vm_map);
did_urls.push(did_url);
}

Ok((vm_maps, did_urls))
}

fn gpg_pk_to_vm(did: &str, cert: Cert) -> Result<(VerificationMethodMap, DIDURL), String> {
let vm_url = DIDURL {
did: did.to_string(),
// NOTE: should this be key_id or fingerprint?
// https://docs.rs/sequoia-openpgp/1.7.0/sequoia_openpgp/struct.Cert.html#method.keyid
fragment: Some(cert.fingerprint().to_string()),
..Default::default()
};

let armored_pgp = String::from_utf8(
cert.armored()
.to_vec()
.map_err(|e| format!("Failed to re-serialize cert: {}", e))?,
)
.map_err(|e| format!("Failed to read cert as utf8: {}", e))?;

let vm_map = VerificationMethodMap {
id: vm_url.to_string(),
type_: "PgpVerificationKey2021".to_string(),
public_key_pgp: Some(armored_pgp),
controller: did.to_string(),
..Default::default()
};
Ok((vm_map, vm_url))
}

fn pk_to_vm_ed25519(
Expand Down Expand Up @@ -348,23 +396,22 @@ mod tests {
);
}

// TODO: use JWK fingerprint
const DID_URL: &str = "https://localhost/user.keys";
const PUBKEYS: &str = include_str!("../tests/ssh_keys");
// localhost web server for serving did:web DID documents.
// TODO: pass arguments here instead of using const
fn web_server() -> Result<(String, impl FnOnce() -> Result<(), ()>), hyper::Error> {
fn web_server(
did_url: &'static str,
pubkeys: &'static str,
) -> Result<(String, impl FnOnce() -> Result<(), ()>), hyper::Error> {
use http::header::{HeaderValue, CONTENT_TYPE};
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Response, Server};
let addr = ([127, 0, 0, 1], 0).into();
let make_svc = make_service_fn(|_| async move {
Ok::<_, hyper::Error>(service_fn(|req| async move {
let make_svc = make_service_fn(move |_| async move {
Ok::<_, hyper::Error>(service_fn(move |req| async move {
let uri = req.uri();
// Skip leading slash
let proxied_url: String = uri.path().chars().skip(1).collect();
if proxied_url == DID_URL {
let body = Body::from(PUBKEYS);
if proxied_url == did_url {
let body = Body::from(pubkeys);
let mut response = Response::new(body);
response
.headers_mut()
Expand Down Expand Up @@ -392,8 +439,12 @@ mod tests {
}

#[tokio::test]
async fn from_did_webkey() {
let (url, shutdown) = web_server().unwrap();
async fn from_did_webkey_ssh() {
// TODO: use JWK fingerprint
let did_url: &str = "https://localhost/user.keys";
let pubkeys: &str = include_str!("../tests/ssh_keys");

let (url, shutdown) = web_server(did_url, pubkeys).unwrap();
PROXY.with(|proxy| {
proxy.replace(Some(url));
});
Expand Down Expand Up @@ -460,4 +511,64 @@ mod tests {
});
shutdown().ok();
}

#[tokio::test]
async fn from_did_webkey_gpg() {
let did_url: &str = "https://localhost/user.gpg";
let pubkeys: &str = include_str!("../tests/user.gpg");

let (url, shutdown) = web_server(did_url, pubkeys).unwrap();
PROXY.with(|proxy| {
proxy.replace(Some(url));
});
let (res_meta, doc_opt, _doc_meta) = DIDWebKey
.resolve(
"did:webkey:gpg:localhost:user.gpg",
&ResolutionInputMetadata::default(),
)
.await;
assert_eq!(res_meta.error, None);
let value_expected = json!({
"@context": "https://www.w3.org/ns/did/v1",
"assertionMethod": [
"did:webkey:gpg:localhost:user.gpg#0CEE8B84B25C0A3C554A9EC1F8FEE972E2A1D935",
"did:webkey:gpg:localhost:user.gpg#6BABBD68A84D5FE3CEEB986EB77927AE619B8EB6",
"did:webkey:gpg:localhost:user.gpg#DCB1FF1899328C0EBB5DF07BD41BBBD1FE58006E"
],
"authentication": [
"did:webkey:gpg:localhost:user.gpg#0CEE8B84B25C0A3C554A9EC1F8FEE972E2A1D935",
"did:webkey:gpg:localhost:user.gpg#6BABBD68A84D5FE3CEEB986EB77927AE619B8EB6",
"did:webkey:gpg:localhost:user.gpg#DCB1FF1899328C0EBB5DF07BD41BBBD1FE58006E"
],
"id": "did:webkey:gpg:localhost:user.gpg",
"verificationMethod": [
{
"controller": "did:webkey:gpg:localhost:user.gpg",
"id": "did:webkey:gpg:localhost:user.gpg#0CEE8B84B25C0A3C554A9EC1F8FEE972E2A1D935",
"publicKeyPgp": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nComment: 0CEE 8B84 B25C 0A3C 554A 9EC1 F8FE E972 E2A1 D935\nComment: Foobar <foobar@example.org>\n\n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\n2YdBRVOAnw==\n=4Vh8\n-----END PGP PUBLIC KEY BLOCK-----\n",
"type": "PgpVerificationKey2021"
},
{
"controller": "did:webkey:gpg:localhost:user.gpg",
"id": "did:webkey:gpg:localhost:user.gpg#6BABBD68A84D5FE3CEEB986EB77927AE619B8EB6",
"publicKeyPgp": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nComment: 6BAB BD68 A84D 5FE3 CEEB 986E B779 27AE 619B 8EB6\nComment: Foobar <foobar@example.org>\n\nxlIEYd3nnBMIKoZIzj0DAQcCAwRhnJmDiD35LzJXstn4zBMfpavUCSkYzyJKIYHe\nOwW4BFe+AF/ZdczzJnx8O1xndvYOFccVNAz7HMb7xPB7MDcEzRtGb29iYXIgPGZv\nb2JhckBleGFtcGxlLm9yZz7CkAQTEwgAOBYhBGurvWioTV/jzuuYbrd5J65hm462\nBQJh3eecAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJELd5J65hm462BNgB\nAKzxt0M3BpEGlAGjz4czrWX8zRdo6XiKeby5yeORfKDEAP4uOuIwE9ics9XICXUg\n1IZhOVNB2cUS6p7Q5ApaqwE3Wc5WBGHd55wSCCqGSM49AwEHAgMEN0OVHjy6Pwyp\nfTci+EKIc486T1EGeYBs/1FErq3bB44Vqr3EsOcdscSqyj3dcxXb47d0kOkiDPKm\nKTy/6ZPWsAMBCAfCeAQYEwgAIBYhBGurvWioTV/jzuuYbrd5J65hm462BQJh3eec\nAhsMAAoJELd5J65hm462KTsA/3vbivQARQMsZfGKptW/SVaKwszMQm2SE+jOESoH\ntk3MAQCjUD7O3CzMX2rCDgLBLh6hwgB3zjn8uaHM1zO9Z48HhQ==\n=Erc7\n-----END PGP PUBLIC KEY BLOCK-----\n",
"type": "PgpVerificationKey2021"
},
{
"controller": "did:webkey:gpg:localhost:user.gpg",
"id": "did:webkey:gpg:localhost:user.gpg#DCB1FF1899328C0EBB5DF07BD41BBBD1FE58006E",
"publicKeyPgp": "-----BEGIN PGP PUBLIC KEY BLOCK-----\nComment: DCB1 FF18 9932 8C0E BB5D F07B D41B BBD1 FE58 006E\nComment: Foobar <foobar@example.org>\n\nxjMEYd3nyxYJKwYBBAHaRw8BAQdAp756gWZbZB66yTjjn52DyUvCxUgFG7aSKqYY\n7KG2KvDNG0Zvb2JhciA8Zm9vYmFyQGV4YW1wbGUub3JnPsKQBBMWCAA4FiEE3LH/\nGJkyjA67XfB71Bu70f5YAG4FAmHd58sCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgEC\nF4AACgkQ1Bu70f5YAG7IMQD7BEg3vAqinv1wllBpXfQov7b4+haxcADWXgmc+06D\nx1QBAMWd6Oa71iKafJKKL3Vgk5q/Sns5+xDvMJmcGbMemckMzjgEYd3nyxIKKwYB\nBAGXVQEFAQEHQECEkuj4GJuUKC0nKvyXoEA1DxJPnASFt2GPC0trMcMoAwEIB8J4\nBBgWCAAgFiEE3LH/GJkyjA67XfB71Bu70f5YAG4FAmHd58sCGwwACgkQ1Bu70f5Y\nAG6eUAEA8vwHBMR4ownA069pQ2EqGhueMoU7YQX0IQBosDf7NrMBAJCoLmuc2dGQ\nT4/C2SFSd3mgOqJXpumOyBFj6hoYkyAI\n=LgN5\n-----END PGP PUBLIC KEY BLOCK-----\n",
"type": "PgpVerificationKey2021"
}
]
});
let doc = doc_opt.unwrap();
let doc_value = serde_json::to_value(doc).unwrap();
eprintln!("doc {}", serde_json::to_string_pretty(&doc_value).unwrap());
assert_eq!(doc_value, value_expected);
PROXY.with(|proxy| {
proxy.replace(None);
});
shutdown().ok();
}
}
59 changes: 59 additions & 0 deletions did-webkey/tests/user.gpg
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
IVJ3eaA6olem6Y7IEWPqGhiTIAg=
=yjPH
-----END PGP PUBLIC KEY BLOCK-----
2 changes: 2 additions & 0 deletions src/did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ pub struct VerificationMethodMap {
// TODO: make sure this JWK does not have private key material
pub public_key_jwk: Option<JWK>,
#[serde(skip_serializing_if = "Option::is_none")]
pub public_key_pgp: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
// TODO: make Base58 type like Base64urlUIntString
pub public_key_base58: Option<String>,
// TODO: ensure that not both key parameters are set
Expand Down

0 comments on commit 7cfb6e7

Please sign in to comment.