mod signing_key_v1;
use super::DataType;
use super::Error;
use super::Header;
use super::HeaderType;
use super::KeySubtype;
use super::Result;
pub use super::SigningKeyVersion;
use signing_key_v1::{SigningKeyV1Pair, SigningKeyV1Public};
use std::convert::TryFrom;
#[cfg(feature = "fuzz")]
use arbitrary::Arbitrary;
#[cfg(feature = "wbindgen")]
use wasm_bindgen::prelude::*;
#[cfg_attr(feature = "wbindgen", wasm_bindgen(inspectable))]
#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
#[derive(Clone, Debug)]
pub struct SigningPublicKey {
pub(crate) header: Header<SigningPublicKey>,
payload: SigningPublicKeyPayload,
}
#[cfg_attr(feature = "wbindgen", wasm_bindgen(inspectable))]
#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
#[derive(Clone, Debug)]
pub struct SigningKeyPair {
pub(crate) header: Header<SigningKeyPair>,
payload: SigningKeyPairPayload,
}
impl HeaderType for SigningPublicKey {
type Version = SigningKeyVersion;
type Subtype = KeySubtype;
fn data_type() -> DataType {
DataType::SigningKey
}
fn subtype() -> Self::Subtype {
KeySubtype::Public
}
}
impl HeaderType for SigningKeyPair {
type Version = SigningKeyVersion;
type Subtype = KeySubtype;
fn data_type() -> DataType {
DataType::SigningKey
}
fn subtype() -> Self::Subtype {
KeySubtype::Private
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
enum SigningKeyPairPayload {
V1(SigningKeyV1Pair),
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
enum SigningPublicKeyPayload {
V1(SigningKeyV1Public),
}
pub fn generate_signing_keypair(version: SigningKeyVersion) -> SigningKeyPair {
let mut header = Header::default();
let payload = match version {
SigningKeyVersion::V1 | SigningKeyVersion::Latest => {
header.version = SigningKeyVersion::V1;
let keypair = signing_key_v1::generate_signing_keypair();
SigningKeyPairPayload::V1(keypair)
}
};
SigningKeyPair { header, payload }
}
impl SigningKeyPair {
pub fn get_public_key(&self) -> SigningPublicKey {
let mut header = Header::default();
let payload = match &self.payload {
SigningKeyPairPayload::V1(x) => {
header.version = SigningKeyVersion::V1;
SigningPublicKeyPayload::V1(x.get_public_key())
}
};
SigningPublicKey { header, payload }
}
}
impl From<SigningPublicKey> for Vec<u8> {
fn from(data: SigningPublicKey) -> Self {
let mut header: Self = data.header.into();
let mut payload: Self = data.payload.into();
header.append(&mut payload);
header
}
}
impl TryFrom<&[u8]> for SigningPublicKey {
type Error = Error;
fn try_from(data: &[u8]) -> Result<Self> {
if data.len() < Header::len() {
return Err(Error::InvalidLength);
};
let header = Header::try_from(&data[0..Header::len()])?;
if header.data_subtype != KeySubtype::Public {
return Err(Error::InvalidDataType);
}
let payload = match header.version {
SigningKeyVersion::V1 => {
SigningPublicKeyPayload::V1(SigningKeyV1Public::try_from(&data[Header::len()..])?)
}
_ => return Err(Error::UnknownVersion),
};
Ok(Self { header, payload })
}
}
impl From<SigningKeyPair> for Vec<u8> {
fn from(data: SigningKeyPair) -> Self {
let mut header: Self = data.header.into();
let mut payload: Self = data.payload.into();
header.append(&mut payload);
header
}
}
impl TryFrom<&[u8]> for SigningKeyPair {
type Error = Error;
fn try_from(data: &[u8]) -> Result<Self> {
if data.len() < Header::len() {
return Err(Error::InvalidLength);
};
let header = Header::try_from(&data[0..Header::len()])?;
if header.data_subtype != KeySubtype::Private {
return Err(Error::InvalidDataType);
}
let payload = match header.version {
SigningKeyVersion::V1 => {
SigningKeyPairPayload::V1(SigningKeyV1Pair::try_from(&data[Header::len()..])?)
}
_ => return Err(Error::UnknownVersion),
};
Ok(Self { header, payload })
}
}
impl From<SigningKeyPairPayload> for Vec<u8> {
fn from(data: SigningKeyPairPayload) -> Self {
match data {
SigningKeyPairPayload::V1(x) => x.into(),
}
}
}
impl From<SigningPublicKeyPayload> for Vec<u8> {
fn from(data: SigningPublicKeyPayload) -> Self {
match data {
SigningPublicKeyPayload::V1(x) => x.into(),
}
}
}
impl From<&SigningPublicKey> for ed25519_dalek::VerifyingKey {
fn from(data: &SigningPublicKey) -> Self {
match &data.payload {
SigningPublicKeyPayload::V1(x) => Self::from(x),
}
}
}
impl From<&SigningKeyPair> for ed25519_dalek::SigningKey {
fn from(data: &SigningKeyPair) -> Self {
match &data.payload {
SigningKeyPairPayload::V1(x) => Self::from(x),
}
}
}
#[test]
fn test_signing_keypair_v1() {
use std::convert::TryInto;
let keypair = generate_signing_keypair(SigningKeyVersion::V1);
let public = keypair.get_public_key();
let keypair_bytes: Vec<u8> = keypair.into();
let public_bytes: Vec<u8> = public.into();
let _: SigningKeyPair = (keypair_bytes.as_slice()).try_into().unwrap();
let _: SigningPublicKey = (public_bytes.as_slice()).try_into().unwrap();
}