Modify X509 signature

Hi there,

I'm quite new on rust and need some help on the following problem:

  1. I use an algorithm for generating a DSA-signature in a distributed manner. That means several participants generate the DSA-signature without any of them knowing the secret key for signature generation. For more info how this works read https://eprint.iacr.org/2019/114.pdf but it is actually not required to know this.
  2. I generated an X509 certificate and imported it to rust using the openssl crate (version 0.10.0)
  3. Now I want to replace the signature value in this X509 certificate with the signature value calculated in step one. As far as I understood, the openssl crate does not provide a method for doing this. Furthermore the datatype Asn1BitString turns out to be a bit tricky.

Does anybody know how I could replace the signature value in the X509-certificate with the one I calculated?

My code looks more or less like this at the moment but obviously doesn't change the signature value at all. All I could achieve was printing the current signature value stored in the imported certificate.

pub fn modcert() -> io::Result<()> {
//get file contents to Vector
let mut f = File::open("dsacert.pem")?;
let mut buffervec = Vec::new();
f.read_to_end(&mut buffervec)?;

//Convert Vector to Bytes
let buffer = buffervec;

//read certificate contents to a X509 struct
let res = X509::from_pem(&buffer);
let res = match res {
    Ok(result) => result,
    Err(error) => {
        panic!("Problem reading the file: {:?}", error)
    },
};

//Print Signature
let sign = res.signature(); //type: Asn1BitString
let sign_alg = res.signature_algorithm();
let sign_vec = sign.as_slice(); //type: &[u8] 
let sign_len = sign.len(); //type: usize
println!("{:?}", (sign_vec, sign_len));

Ok(())

}

fn main() {

    let r = modcert();  

}

From my naive skimming of the X509 docs, it looks like modifying the signature in place is something that the library really does not want you to do, as the method for getting the signature returns a special immutable ref wrapper and there doesn't seem to be a mutable counterpart. This may be a circumstance where the library maintainers thought this would be usually more of a foot-gun than a help, and so intentionally made it more difficult.

Would it be acceptable to just build a new X509 object using the information decoded and a X509Builder? If your factoring and performance requirements permit this, it might be a faster and easier path to victory.

Yes it would be an alternative to build a new X509 object. But the X509Builder of the openssl crate doesn't support this. How would you do this?

OK, I looked into it and the builder is also not very helpful. From what I can tell, the whole OpenSSL X509 Rust library is a thin wrapper around a foreign function interface to OpenSSL. OpenSSL itself does not seem to provide easy access to update an X509 object's signature, and expects to sign it itself.

I'm not an OpenSSL expert. Maybe someone familiar with the internals of what is going on can provide you with a more helpful solution. From my limited understanding, my guess is that OpenSSL will not easily cooperate with what you want it to do, leaving you with two options:

  1. Coerce OpenSSL to do what you want it to do. This may require you to dive into the underlying C.
  2. Use a different library for the parsing/updating of the X509 certificate and reserialize it to get it into the OpenSSL world. I see that there exist X509 pure-Rust libraries, although I haven't the foggiest how mature they are or how well they work.