@@ -75,13 +75,17 @@ impl RekorClient {
7575 }
7676
7777 /// Build a hashedrekord v0.0.1 request from attestation data.
78+ ///
79+ /// Wraps the raw public key in PKIX/SPKI DER before base64 encoding,
80+ /// which is the format Sigstore tooling (cosign, rekor-cli) expects.
7881 fn build_hashedrekord (
7982 & self ,
8083 leaf_data : & [ u8 ] ,
8184 public_key : & [ u8 ] ,
8285 signature : & [ u8 ] ,
8386 ) -> HashedRekordRequest {
8487 let data_hash = hex:: encode ( Sha256 :: digest ( leaf_data) ) ;
88+ let der_key = wrap_pubkey_in_spki_der ( public_key) ;
8589
8690 HashedRekordRequest {
8791 api_version : "0.0.1" . to_string ( ) ,
@@ -90,7 +94,7 @@ impl RekorClient {
9094 signature : HashedRekordSignature {
9195 content : BASE64 . encode ( signature) ,
9296 public_key : HashedRekordPublicKey {
93- content : BASE64 . encode ( public_key ) ,
97+ content : BASE64 . encode ( & der_key ) ,
9498 } ,
9599 } ,
96100 data : HashedRekordData {
@@ -461,6 +465,43 @@ impl TransparencyLog for RekorClient {
461465 }
462466}
463467
468+ /// Wrap raw public key bytes in SPKI DER for Sigstore compatibility.
469+ ///
470+ /// Sigstore tooling (cosign, rekor-cli) expects PKIX/SPKI DER-encoded keys.
471+ /// Uses the `p256` crate for P-256 keys to produce correct ASN.1 encoding.
472+ /// Ed25519 uses RFC 8410 SPKI format (fixed 12-byte header + 32-byte key).
473+ fn wrap_pubkey_in_spki_der ( raw : & [ u8 ] ) -> Vec < u8 > {
474+ match raw. len ( ) {
475+ 32 => {
476+ // Ed25519 SPKI per RFC 8410:
477+ // SEQUENCE { SEQUENCE { OID 1.3.101.112 }, BIT STRING { key } }
478+ // Fixed 12-byte header: 30 2a 30 05 06 03 2b6570 03 21 00
479+ let mut der = Vec :: with_capacity ( 44 ) ;
480+ der. extend_from_slice ( & [
481+ 0x30 , 0x2a , // SEQUENCE, 42 bytes total
482+ 0x30 , 0x05 , // SEQUENCE, 5 bytes (AlgorithmIdentifier)
483+ 0x06 , 0x03 , 0x2b , 0x65 , 0x70 , // OID 1.3.101.112 (id-EdDSA / Ed25519)
484+ 0x03 , 0x21 , 0x00 , // BIT STRING, 33 bytes, 0 unused bits
485+ ] ) ;
486+ der. extend_from_slice ( raw) ;
487+ der
488+ }
489+ 33 | 65 => {
490+ // P-256: use the p256 crate to produce correct SPKI DER
491+ use p256:: pkcs8:: EncodePublicKey ;
492+ let vk = match p256:: ecdsa:: VerifyingKey :: from_sec1_bytes ( raw) {
493+ Ok ( vk) => vk,
494+ Err ( _) => return raw. to_vec ( ) ,
495+ } ;
496+ match vk. to_public_key_der ( ) {
497+ Ok ( der) => der. as_ref ( ) . to_vec ( ) ,
498+ Err ( _) => raw. to_vec ( ) ,
499+ }
500+ }
501+ _ => raw. to_vec ( ) ,
502+ }
503+ }
504+
464505#[ cfg( test) ]
465506mod tests {
466507 use super :: * ;
0 commit comments