@@ -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 {
@@ -139,12 +179,19 @@ impl FulcioClient {
139
179
let signature = BASE64_STD_ENGINE . encode ( signature) ;
140
180
141
181
let key_pair = signer. to_sigstore_keypair ( ) ?;
142
- let public_key = key_pair. public_key_to_der ( ) ?;
143
- let public_key = BASE64_STD_ENGINE . encode ( public_key) ;
144
-
182
+ let public_key = key_pair. public_key_to_pem ( ) ?;
145
183
let csr = Csr {
146
- public_key : Some ( PublicKey ( public_key, signing_scheme) ) ,
147
- signed_email_address : Some ( signature) ,
184
+ credentials : Credentials {
185
+ oidc_identity_token : token. to_string ( ) ,
186
+ } ,
187
+ public_key_request : PublicKeyRequest {
188
+ public_key : PublicKey {
189
+ algorithm : Some ( signing_scheme) ,
190
+ content : public_key,
191
+ } ,
192
+ proof_of_possession : signature,
193
+ } ,
194
+ certificate_signing_request : None ,
148
195
} ;
149
196
150
197
let csr: Body = csr. try_into ( ) ?;
@@ -159,11 +206,24 @@ impl FulcioClient {
159
206
. await
160
207
. map_err ( |_| SigstoreError :: SigstoreFulcioCertificatesNotProvidedError ) ?;
161
208
162
- let cert = response
163
- . text ( )
209
+ let cert_response = response
210
+ . json :: < CsrResponse > ( )
164
211
. await
165
212
. map_err ( |_| SigstoreError :: SigstoreFulcioCertificatesNotProvidedError ) ?;
166
213
167
- Ok ( ( signer, FulcioCert ( cert) ) )
214
+ let cert: FulcioCert ;
215
+
216
+ if let Some ( signed_certificate_detached_sct) = cert_response. signed_certificate_detached_sct
217
+ {
218
+ cert = signed_certificate_detached_sct. chain . certificates [ 0 ] . clone ( ) ;
219
+ } else if let Some ( signed_certificate_embedded_sct) =
220
+ cert_response. signed_certificate_embedded_sct
221
+ {
222
+ cert = signed_certificate_embedded_sct. chain . certificates [ 0 ] . clone ( ) ;
223
+ } else {
224
+ return Err ( SigstoreError :: CertificateRequestError ) ;
225
+ }
226
+
227
+ Ok ( ( signer, cert) )
168
228
}
169
229
}
0 commit comments