Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions ic-agent/src/identity/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,41 @@ impl BasicIdentity {
/// Create a `BasicIdentity` from reading a PEM File from a Reader.
#[cfg(feature = "pem")]
pub fn from_pem<R: std::io::Read>(pem_reader: R) -> Result<Self, PemError> {
use der::{Decode, PemReader};
use der::{asn1::OctetString, Decode, ErrorKind, SliceReader, Tag, TagNumber};
use pkcs8::PrivateKeyInfo;

let bytes: Vec<u8> = pem_reader
.bytes()
.collect::<Result<Vec<u8>, std::io::Error>>()?;
let pki = PrivateKeyInfo::decode(&mut PemReader::new(&bytes)?)?;
let private_key = SigningKey::try_from(pki.private_key)?;
let bytes: Vec<u8> = pem_reader.bytes().collect::<Result<_, _>>()?;
let pem = pem::parse(bytes)?;
let pki_res = PrivateKeyInfo::decode(&mut SliceReader::new(pem.contents())?);
let mut truncated;
let pki = match pki_res {
Ok(pki) => pki,
Err(e) => {
if e.kind()
== (ErrorKind::Noncanonical {
tag: Tag::ContextSpecific {
constructed: true,
number: TagNumber::new(1),
},
})
{
// Very old versions of dfx generated nonconforming containers. They can only be imported if the extra data is removed.
truncated = pem.into_contents();
if truncated[48..52] != *b"\xA1\x23\x03\x21" {
return Err(e.into());
}
// hatchet surgery
truncated.truncate(48);
truncated[1] = 46;
truncated[4] = 0;
PrivateKeyInfo::decode(&mut SliceReader::new(&truncated)?).map_err(|_| e)?
} else {
return Err(e.into());
}
}
};
let decoded_key = OctetString::from_der(pki.private_key)?; // ed25519 uses an octet string within another octet string
let private_key = SigningKey::try_from(decoded_key.as_bytes())?;
Ok(BasicIdentity::from_signing_key(private_key))
}

Expand Down
Loading