use crate::Keypair;
use anyhow::{Result, anyhow};
use schnorrkel::{KEYPAIR_LENGTH, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH};
pub struct KeypairInfo {
pub secret: [u8; SECRET_KEY_LENGTH],
pub public: [u8; PUBLIC_KEY_LENGTH],
}
impl KeypairInfo {
pub const ENCODED_LENGTH: usize = 117;
const PKCS8_HEADER_LENGTH: usize = 16;
const PKCS8_HEADER: [u8; Self::PKCS8_HEADER_LENGTH] =
[48, 83, 2, 1, 1, 48, 5, 6, 3, 43, 101, 112, 4, 34, 4, 32];
const PKCS8_DIVIDER_LENGTH: usize = 5;
const PKCS8_DIVIDER: [u8; Self::PKCS8_DIVIDER_LENGTH] = [161, 35, 3, 33, 0];
const SECRET_KEY_OFFSET: usize = Self::PKCS8_HEADER_LENGTH;
const PKCS8_DIVIDER_OFFSET: usize = Self::PKCS8_HEADER_LENGTH + SECRET_KEY_LENGTH;
const PUBLIC_KEY_OFFSET: usize =
Self::SECRET_KEY_OFFSET + SECRET_KEY_LENGTH + Self::PKCS8_DIVIDER_LENGTH;
pub fn decode(data: &[u8]) -> Result<Self> {
if data[..Self::PKCS8_HEADER_LENGTH] != Self::PKCS8_HEADER {
return Err(anyhow!("invalid pkcs8 header"));
}
if data[Self::PKCS8_DIVIDER_OFFSET..Self::PKCS8_DIVIDER_OFFSET + Self::PKCS8_DIVIDER_LENGTH]
!= Self::PKCS8_DIVIDER
{
return Err(anyhow!("invalid pkcs8 divider"));
}
let mut encoded = [0; Self::ENCODED_LENGTH];
encoded.copy_from_slice(data);
let mut secret = [0u8; SECRET_KEY_LENGTH];
let mut public = [0u8; PUBLIC_KEY_LENGTH];
secret.copy_from_slice(
&encoded[Self::SECRET_KEY_OFFSET..Self::SECRET_KEY_OFFSET + SECRET_KEY_LENGTH],
);
public.copy_from_slice(
&encoded[Self::PUBLIC_KEY_OFFSET..Self::PUBLIC_KEY_OFFSET + PUBLIC_KEY_LENGTH],
);
Ok(Self { secret, public })
}
pub fn encode(&self) -> [u8; Self::ENCODED_LENGTH] {
let mut encoded = [0; Self::ENCODED_LENGTH];
encoded[..Self::PKCS8_HEADER_LENGTH].copy_from_slice(&Self::PKCS8_HEADER);
encoded[Self::SECRET_KEY_OFFSET..Self::SECRET_KEY_OFFSET + SECRET_KEY_LENGTH]
.copy_from_slice(&self.secret);
encoded
[Self::PKCS8_DIVIDER_OFFSET..Self::PKCS8_DIVIDER_OFFSET + Self::PKCS8_DIVIDER_LENGTH]
.copy_from_slice(&Self::PKCS8_DIVIDER);
encoded[Self::PUBLIC_KEY_OFFSET..Self::PUBLIC_KEY_OFFSET + PUBLIC_KEY_LENGTH]
.copy_from_slice(&self.public);
encoded
}
pub fn into_keypair(self) -> Result<Keypair> {
let mut bytes = [0u8; KEYPAIR_LENGTH];
bytes[..SECRET_KEY_LENGTH].copy_from_slice(&self.secret);
bytes[SECRET_KEY_LENGTH..].copy_from_slice(&self.public);
Keypair::from_half_ed25519_bytes(&bytes)
.map_err(|e| anyhow!("Failed to create pair: {e:?}"))
}
}
impl From<Keypair> for KeypairInfo {
fn from(keypair: Keypair) -> Self {
let secret = keypair.secret.to_ed25519_bytes();
let public = keypair.public.to_bytes();
Self { secret, public }
}
}