@@ -8,7 +8,7 @@ use base64::{engine::general_purpose::STANDARD as BASE64_STD_ENGINE, Engine as _
8
8
use openidconnect:: core:: CoreIdToken ;
9
9
use reqwest:: Body ;
10
10
use serde:: ser:: SerializeStruct ;
11
- use serde:: { Serialize , Serializer } ;
11
+ use serde:: { Deserialize , Serialize , Serializer } ;
12
12
use std:: convert:: { TryFrom , TryInto } ;
13
13
use std:: fmt:: { Debug , Display , Formatter } ;
14
14
use url:: Url ;
@@ -17,19 +17,63 @@ use url::Url;
17
17
pub const FULCIO_ROOT : & str = "https://fulcio.sigstore.dev/" ;
18
18
19
19
/// Path within Fulcio to obtain a signing certificate.
20
- pub const SIGNING_CERT_PATH : & str = "api/v1 /signingCert" ;
20
+ pub const SIGNING_CERT_PATH : & str = "api/v2 /signingCert" ;
21
21
22
22
const CONTENT_TYPE_HEADER_NAME : & str = "content-type" ;
23
23
24
+ #[ derive( Serialize , Debug ) ]
25
+ #[ serde( rename_all = "camelCase" ) ]
26
+ struct Credentials {
27
+ oidc_identity_token : String ,
28
+ }
29
+
30
+ #[ derive( Debug ) ]
31
+ struct PublicKey {
32
+ algorithm : Option < SigningScheme > ,
33
+ content : String ,
34
+ }
35
+ impl Serialize for PublicKey {
36
+ fn serialize < S : Serializer > ( & self , serializer : S ) -> std:: result:: Result < S :: Ok , S :: Error >
37
+ where
38
+ S : Serializer ,
39
+ {
40
+ let mut pk = serializer. serialize_struct ( "PublicKey" , 2 ) ?;
41
+ pk. serialize_field ( "content" , & self . content ) ?;
42
+ pk. serialize_field (
43
+ "algorithm" ,
44
+ match self . algorithm {
45
+ Some ( SigningScheme :: ECDSA_P256_SHA256_ASN1 )
46
+ | Some ( SigningScheme :: ECDSA_P384_SHA384_ASN1 ) => "ECDSA" ,
47
+ Some ( SigningScheme :: ED25519 ) => "ED25519" ,
48
+ Some ( SigningScheme :: RSA_PSS_SHA256 ( _) )
49
+ | Some ( SigningScheme :: RSA_PSS_SHA384 ( _) )
50
+ | Some ( SigningScheme :: RSA_PSS_SHA512 ( _) )
51
+ | Some ( SigningScheme :: RSA_PKCS1_SHA256 ( _) )
52
+ | Some ( SigningScheme :: RSA_PKCS1_SHA384 ( _) )
53
+ | Some ( SigningScheme :: RSA_PKCS1_SHA512 ( _) ) => "RSA" ,
54
+ _ => "PUBLIC_KEY_ALGORITHM_UNSPECIFIED" ,
55
+ } ,
56
+ ) ?;
57
+ pk. end ( )
58
+ }
59
+ }
60
+
61
+ #[ derive( Serialize , Debug ) ]
62
+ #[ serde( rename_all = "camelCase" ) ]
63
+ struct PublicKeyRequest {
64
+ public_key : PublicKey ,
65
+ proof_of_possession : String ,
66
+ }
24
67
/// Fulcio certificate signing request
25
68
///
26
69
/// Used to present a public key and signed challenge/proof-of-key in exchange
27
70
/// for a signed X509 certificate in return.
28
71
#[ derive( Serialize , Debug ) ]
29
72
#[ serde( rename_all = "camelCase" ) ]
30
73
struct Csr {
31
- public_key : Option < PublicKey > ,
32
- signed_email_address : Option < String > ,
74
+ credentials : Credentials ,
75
+ public_key_request : PublicKeyRequest ,
76
+ certificate_signing_request : Option < String > ,
33
77
}
34
78
35
79
impl TryFrom < Csr > for Body {
@@ -40,37 +84,33 @@ impl TryFrom<Csr> for Body {
40
84
}
41
85
}
42
86
43
- /// Internal newtype to control serde jsonification.
44
- #[ derive( Debug ) ]
45
- struct PublicKey ( String , SigningScheme ) ;
87
+ #[ derive( Deserialize ) ]
88
+ #[ serde( rename_all = "camelCase" ) ]
89
+ struct Chain {
90
+ certificates : Vec < FulcioCert > ,
91
+ }
46
92
47
- impl Serialize for PublicKey {
48
- fn serialize < S : Serializer > ( & self , serializer : S ) -> std:: result:: Result < S :: Ok , S :: Error >
49
- where
50
- S : Serializer ,
51
- {
52
- let mut pk = serializer. serialize_struct ( "PublicKey" , 2 ) ?;
53
- pk. serialize_field ( "content" , & self . 0 ) ?;
54
- pk. serialize_field (
55
- "algorithm" ,
56
- match self . 1 {
57
- SigningScheme :: ECDSA_P256_SHA256_ASN1 | SigningScheme :: ECDSA_P384_SHA384_ASN1 => {
58
- "ecdsa"
59
- }
60
- SigningScheme :: ED25519 => "ed25519" ,
61
- SigningScheme :: RSA_PSS_SHA256 ( _)
62
- | SigningScheme :: RSA_PSS_SHA384 ( _)
63
- | SigningScheme :: RSA_PSS_SHA512 ( _)
64
- | SigningScheme :: RSA_PKCS1_SHA256 ( _)
65
- | SigningScheme :: RSA_PKCS1_SHA384 ( _)
66
- | SigningScheme :: RSA_PKCS1_SHA512 ( _) => "rsa" ,
67
- } ,
68
- ) ?;
69
- pk. end ( )
70
- }
93
+ #[ derive( Deserialize ) ]
94
+ #[ serde( rename_all = "camelCase" ) ]
95
+ struct SignedCertificateDetachedSct {
96
+ chain : Chain ,
97
+ }
98
+
99
+ #[ derive( Deserialize ) ]
100
+ #[ serde( rename_all = "camelCase" ) ]
101
+ struct SignedCertificateEmbeddedSct {
102
+ chain : Chain ,
103
+ }
104
+
105
+ #[ derive( Deserialize ) ]
106
+ #[ serde( rename_all = "camelCase" ) ]
107
+ struct CsrResponse {
108
+ signed_certificate_detached_sct : Option < SignedCertificateDetachedSct > ,
109
+ signed_certificate_embedded_sct : Option < SignedCertificateEmbeddedSct > ,
71
110
}
72
111
73
112
/// The PEM-encoded certificate chain returned by Fulcio.
113
+ #[ derive( Deserialize , Clone ) ]
74
114
pub struct FulcioCert ( String ) ;
75
115
76
116
impl AsRef < [ u8 ] > for FulcioCert {
@@ -164,12 +204,19 @@ impl FulcioClient {
164
204
let signature = BASE64_STD_ENGINE . encode ( signature) ;
165
205
166
206
let key_pair = signer. to_sigstore_keypair ( ) ?;
167
- let public_key = key_pair. public_key_to_der ( ) ?;
168
- let public_key = BASE64_STD_ENGINE . encode ( public_key) ;
169
-
207
+ let public_key = key_pair. public_key_to_pem ( ) ?;
170
208
let csr = Csr {
171
- public_key : Some ( PublicKey ( public_key, signing_scheme) ) ,
172
- signed_email_address : Some ( signature) ,
209
+ credentials : Credentials {
210
+ oidc_identity_token : token. to_string ( ) ,
211
+ } ,
212
+ public_key_request : PublicKeyRequest {
213
+ public_key : PublicKey {
214
+ algorithm : Some ( signing_scheme) ,
215
+ content : public_key,
216
+ } ,
217
+ proof_of_possession : signature,
218
+ } ,
219
+ certificate_signing_request : None ,
173
220
} ;
174
221
175
222
let csr = TryInto :: < Body > :: try_into ( csr) ?;
@@ -184,11 +231,24 @@ impl FulcioClient {
184
231
. await
185
232
. map_err ( |_| SigstoreError :: SigstoreFulcioCertificatesNotProvidedError ) ?;
186
233
187
- let cert = response
188
- . text ( )
234
+ let cert_response = response
235
+ . json :: < CsrResponse > ( )
189
236
. await
190
237
. map_err ( |_| SigstoreError :: SigstoreFulcioCertificatesNotProvidedError ) ?;
191
238
192
- Ok ( ( signer, FulcioCert ( cert) ) )
239
+ let cert: FulcioCert ;
240
+
241
+ if let Some ( signed_certificate_detached_sct) = cert_response. signed_certificate_detached_sct
242
+ {
243
+ cert = signed_certificate_detached_sct. chain . certificates [ 0 ] . clone ( ) ;
244
+ } else if let Some ( signed_certificate_embedded_sct) =
245
+ cert_response. signed_certificate_embedded_sct
246
+ {
247
+ cert = signed_certificate_embedded_sct. chain . certificates [ 0 ] . clone ( ) ;
248
+ } else {
249
+ return Err ( SigstoreError :: CertificateRequestError ) ;
250
+ }
251
+
252
+ Ok ( ( signer, cert) )
193
253
}
194
254
}
0 commit comments