forked from OKEAMAH/didkit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkey.rs
More file actions
153 lines (139 loc) · 4.58 KB
/
key.rs
File metadata and controls
153 lines (139 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use std::io::{stdout, BufWriter};
use anyhow::Result;
use clap::{Args, Subcommand};
use didkit::{get_verification_method, ssi::ssh, Error, Source, DID_METHODS, JWK};
use sshkeys::PublicKey;
#[derive(Subcommand)]
pub enum KeyCmd {
/// Generate and output a keypair in JWK format
#[clap(subcommand)]
Generate(KeyGenerateCmd),
/// Transform a key (e.g. JWK) into other formats (e.g. DIDs)
#[clap(subcommand)]
To(Box<KeyToCmd>),
/// Get a key (e.g. JWK) from other formats (e.g. SSH public key)
#[clap(subcommand)]
From(Box<KeyFromCmd>),
}
#[derive(Subcommand)]
pub enum KeyToCmd {
/// Output a DID for a given JWK according to the provided DID method name or pattern
///
/// Deterministically generate a DID from a public key JWK, for a DID method
/// that support this functionality.
///
/// The DID method to use may be provided in the `method-pattern` argument. The default is
/// "key", corresponding to did:key.
///
/// For DID methods that have multiple ways of representing a key, `method-pattern` is
/// method-specific but typically is a prefix, for example "pkh:tz" to generate a DID that
/// begins with `did:pkh:tz`.
Did(KeyToDIDArgs),
/// Output a verificationMethod DID URL for a JWK and DID method name/pattern
VerificationMethod(KeyToVMArgs),
}
#[derive(Subcommand)]
pub enum KeyFromCmd {
/// Convert a SSH public key to a JWK
Ssh(KeyFromSSHArgs),
}
#[derive(Subcommand)]
pub enum KeyGenerateCmd {
/// Generate and output a Ed25519 keypair in JWK format
Ed25519,
/// Generate and output a K-256 keypair in JWK format
Secp256k1,
/// Generate and output a P-256 keypair in JWK format
Secp256r1,
}
#[derive(Args)]
pub struct KeyToDIDArgs {
/// DID method name or pattern. e.g. `key`, `tz`, or `pkh:tz`
#[clap(default_value = "key")]
pub method_pattern: String,
#[clap(flatten)]
pub key: crate::KeyArg,
}
#[derive(Args)]
pub struct KeyToVMArgs {
/// DID method id or pattern. e.g. `key`, `tz`, or `pkh:tz`
pub method_pattern: Option<String>,
#[clap(flatten)]
pub key: crate::KeyArg,
}
#[derive(Args)]
pub struct KeyFromSSHArgs {
/// SSH Public Key
ssh_pk: String,
}
pub async fn cli(cmd: KeyCmd) -> Result<()> {
match cmd {
KeyCmd::Generate(cmd_generate) => generate(cmd_generate).await?,
KeyCmd::To(cmd_to) => to(*cmd_to).await?,
KeyCmd::From(cmd_from) => from(*cmd_from).await?,
};
Ok(())
}
pub async fn to(cmd: KeyToCmd) -> Result<()> {
match cmd {
KeyToCmd::Did(cmd_did) => to_did(cmd_did).await?,
KeyToCmd::VerificationMethod(cmd_vm) => to_vm(cmd_vm).await?,
};
Ok(())
}
pub async fn from(cmd: KeyFromCmd) -> Result<()> {
match cmd {
KeyFromCmd::Ssh(cmd_ssh) => from_ssh(cmd_ssh).await?,
};
Ok(())
}
pub async fn generate(cmd: KeyGenerateCmd) -> Result<()> {
let jwk = match cmd {
KeyGenerateCmd::Ed25519 => JWK::generate_ed25519().unwrap(),
KeyGenerateCmd::Secp256k1 => JWK::generate_secp256k1().unwrap(),
KeyGenerateCmd::Secp256r1 => JWK::generate_p256().unwrap(),
};
let jwk_str = serde_json::to_string(&jwk).unwrap();
println!("{jwk_str}");
Ok(())
}
pub async fn to_did(args: KeyToDIDArgs) -> Result<()> {
let jwk = args.key.get_jwk();
let did = DID_METHODS
.generate(&Source::KeyAndPattern(&jwk, &args.method_pattern))
.ok_or(Error::UnableToGenerateDID)
.unwrap();
println!("{did}");
Ok(())
}
pub async fn to_vm(args: KeyToVMArgs) -> Result<()> {
let method_pattern = match args.method_pattern {
Some(pattern) => pattern,
None => {
eprintln!(
"didkit: key-to-verification-method should be used with method pattern option"
);
"key".to_string()
}
};
let jwk = args.key.get_jwk();
let did = DID_METHODS
.generate(&Source::KeyAndPattern(&jwk, &method_pattern))
.ok_or(Error::UnableToGenerateDID)
.unwrap();
let did_resolver = DID_METHODS.to_resolver();
let vm = get_verification_method(&did, did_resolver)
.await
.ok_or(Error::UnableToGetVerificationMethod)
.unwrap();
println!("{vm}");
Ok(())
}
pub async fn from_ssh(args: KeyFromSSHArgs) -> Result<()> {
// Deserializing here because PublicKey doesn't derive Clone
let ssh_pk = PublicKey::from_string(&args.ssh_pk).unwrap();
let jwk = ssh::ssh_pkk_to_jwk(&ssh_pk.kind).unwrap();
let stdout_writer = BufWriter::new(stdout());
serde_json::to_writer_pretty(stdout_writer, &jwk).unwrap();
Ok(())
}