Search code examples
rustopenssl

How to display an OpenSSL signature?


My attempt with String::from_utf8 returns an error:

fn main() {
    let group = EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
    let pair = PKey::from_ec_key(EcKey::generate(&group).unwrap()).unwrap();
    println!(
        "Public: {:?}",
        String::from_utf8(pair.public_key_to_pem().unwrap())
    );
    println!(
        "Private: {:?}",
        String::from_utf8(pair.private_key_to_pem_pkcs8().unwrap())
    );

    let data = b"hello";

    let mut signer = Signer::new(MessageDigest::sha512(), &pair).unwrap();
    signer.update(data).unwrap();

    let signature = signer.sign_to_vec().unwrap();

    println!("Signature: {:?}", String::from_utf8(signature));
}
Public: Ok("-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n")
Private: Ok("-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n")
Signature: Err(FromUtf8Error { bytes: [48, 69, 2, 33, 0, 221, 124, 107, 80, 118, 244, 208, 146, 83, 198, 12, 244, 45, 218, 184, 160, 152, 119, 117, 176, 124, 209, 252, 115, 173, 49, 31, 84, 247, 201, 187, 233, 2, 32, 1, 126, 10, 149, 78, 239, 13, 110, 84, 60, 81, 111, 252, 195, 246, 214, 176, 157, 116, 65, 125, 75, 66, 164, 207, 110, 141, 203, 85, 60, 111, 126], error: Utf8Error { valid_up_to: 5, error_len: Some(1) } })

How can I get the signature as a String?


Solution

  • The public and private keys are here represented in the PEM format, which is human readable and therefore storable in a String.

    The signature, however, gets returned as raw binary data. It is not human readable and therefore not directly storable in a string.

    If you still want to store it in a string, you have to convert it into a human readable encoding, like base64:

    use openssl::{
        ec::{EcGroup, EcKey},
        hash::MessageDigest,
        nid::Nid,
        pkey::PKey,
        sign::Signer,
    };
    
    fn main() {
        let group = EcGroup::from_curve_name(Nid::SECP256K1).unwrap();
        let pair = PKey::from_ec_key(EcKey::generate(&group).unwrap()).unwrap();
        println!(
            "Public:\n{}\n",
            String::from_utf8(pair.public_key_to_pem().unwrap()).unwrap()
        );
        println!(
            "Private:\n{}\n",
            String::from_utf8(pair.private_key_to_pem_pkcs8().unwrap()).unwrap()
        );
    
        let data = b"hello";
    
        let mut signer = Signer::new(MessageDigest::sha512(), &pair).unwrap();
        signer.update(data).unwrap();
    
        let signature = signer.sign_to_vec().unwrap();
    
        let signature_base64 = base64::encode(signature);
    
        println!("Signature:\n{}\n", signature_base64);
    }
    
    Public:
    -----BEGIN PUBLIC KEY-----
    MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEfC8hXiKyuS2U/Kcg+HQuKYA+29wYZeGj
    lOSTeMhj7xTqktPrCONJg1Acb1rjqU4kNdMEzUMwKemoqT0OWe/5yw==
    -----END PUBLIC KEY-----
    
    
    Private:
    -----BEGIN PRIVATE KEY-----
    MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQg64c0IelDNgh9MsROvoGQ
    TCUMbklvGtWF1RcLhsdLefmhRANCAAR8LyFeIrK5LZT8pyD4dC4pgD7b3Bhl4aOU
    5JN4yGPvFOqS0+sI40mDUBxvWuOpTiQ10wTNQzAp6aipPQ5Z7/nL
    -----END PRIVATE KEY-----
    
    
    Signature:
    MEUCIEnP49eZTk6y624A+FPCLIWNEpkZMj82QOu99BFi6r/tAiEA7ThuWNF/j5hTSw8N2MNOv1D3fU4a7ThYz1cu/jQJNrk=
    

    Note that if you want to use it for verification later, you have to convert the base64 encoded string back to its raw representation.