diff --git a/build.rs b/build.rs
index cac13b579a05e5d8a34ca7108be4e4356210e0e9..70844b045766775dfa9843e0e2aa63773dad33c1 100644
--- a/build.rs
+++ b/build.rs
@@ -43,15 +43,30 @@ fn main() {
     pkey.check_key().unwrap();
     assert_eq!(pkey.group().curve_name(), Some(Nid::X9_62_PRIME256V1));
 
-    let mut priv_key = pkey.private_key().to_vec();
-    if priv_key.len() == 33 && priv_key[0] == 0 {
-        priv_key.remove(0);
-    }
-    assert_eq!(priv_key.len(), 32);
+    // Private keys generated by OpenSSL have variable size but we only handle
+    // constant size. Serialization is done in big endian so if the size is less
+    // than 32 bytes, we need to prepend with null bytes.
+    // If the size is 33 bytes, this means the serialized BigInt is negative.
+    // Any other size is invalid.
+    let priv_key_hex = pkey.private_key().to_hex_str().unwrap();
+    let priv_key_vec = pkey.private_key().to_vec();
+    let key_len = priv_key_vec.len();
+
+    assert!(
+        key_len <= 33,
+        "Invalid private key (too big): {} ({:#?})",
+        priv_key_hex,
+        priv_key_vec,
+    );
+
+    // Copy OpenSSL generated key to our vec, starting from the end
+    let mut output_vec = [0u8; 32];
+    let min_key_len = std::cmp::min(key_len, 32);
+    output_vec[32 - min_key_len..].copy_from_slice(&priv_key_vec[key_len - min_key_len..]);
 
     // Create the raw private key out of the OpenSSL data
     let mut priv_key_bin_file = File::create(&priv_key_bin_path).unwrap();
-    priv_key_bin_file.write_all(&priv_key).unwrap();
+    priv_key_bin_file.write_all(&output_vec).unwrap();
 
     // Convert the PEM certificate to DER and extract the serial for AAGUID
     let input_pem_cert = include_bytes!("crypto_data/opensk_cert.pem");