dat 2.3.0

DAT - Distributed Access Token
Documentation
use crate::error::DatError;
use crate::signature_algorithm::DatSignatureAlgorithm;
use aws_lc_rs::signature::{EcdsaKeyPair, KeyPair, UnparsedPublicKey, ECDSA_P256_SHA256_FIXED, ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P384_SHA384_FIXED, ECDSA_P384_SHA384_FIXED_SIGNING, ECDSA_P521_SHA512_FIXED, ECDSA_P521_SHA512_FIXED_SIGNING};
use strum_macros::{Display, EnumString};

#[repr(u8)]
#[derive(Debug, Display, EnumString, Clone, Copy, Eq, PartialEq)]
pub enum DatSignatureKeyOutOption {
    FULL,
    SIGNING,
    VERIFYING,
}

pub struct DatSignatureKey {
    algorithm: DatSignatureAlgorithm,
    signing_key: Option<EcdsaKeyPair>,
    signing_key_bytes: Vec<u8>,
    verifying_key: UnparsedPublicKey<Vec<u8>>,
}

impl DatSignatureKey {
    pub fn generate(algorithm: DatSignatureAlgorithm) -> Result<Self, DatError> {
        Self::from_or_new(true, algorithm, &[], &[])
    }

    pub fn from_bytes(algorithm: DatSignatureAlgorithm, signing_key_bytes: &[u8], verifying_key_bytes: &[u8]) -> Result<DatSignatureKey, DatError> {
        Self::from_or_new(false, algorithm, signing_key_bytes, verifying_key_bytes)
    }
    fn from_or_new(new: bool, algorithm: DatSignatureAlgorithm, signing_key_bytes: &[u8], verifying_key_bytes: &[u8]) -> Result<DatSignatureKey, DatError> {
        let (sa, va) = match algorithm {
            DatSignatureAlgorithm::P256 => &(ECDSA_P256_SHA256_FIXED_SIGNING, ECDSA_P256_SHA256_FIXED),
            DatSignatureAlgorithm::P384 => &(ECDSA_P384_SHA384_FIXED_SIGNING, ECDSA_P384_SHA384_FIXED),
            DatSignatureAlgorithm::P521 => &(ECDSA_P521_SHA512_FIXED_SIGNING, ECDSA_P521_SHA512_FIXED),
        };
        let rng = aws_lc_rs::rand::SystemRandom::new();

        let mut signing_key_bytes = Vec::from(signing_key_bytes);
        let mut verifying_key_bytes = Vec::from(verifying_key_bytes);
        let pkcs8_private_key = if new {
            let pkcs8_private_key = Vec::from(EcdsaKeyPair::generate_pkcs8(sa, &rng).map_err(|_| DatError::CreateDatSigningKeyError)?.as_ref());
            signing_key_bytes = to_raw(algorithm, &pkcs8_private_key)?;
            pkcs8_private_key
        } else {
            to_pkcs8_der(algorithm, &signing_key_bytes)?
        };

        let signing_key: Option<EcdsaKeyPair> = if pkcs8_private_key.is_empty() {
            None
        } else {
            let sk = EcdsaKeyPair::from_pkcs8(sa, &*pkcs8_private_key)
                .map_err(|_| { DatError::ParseDatSigningKeyError })?;
            if verifying_key_bytes.is_empty() {
                verifying_key_bytes = Vec::from(sk.public_key().as_ref());
            }
            Some(sk)
        };

        if verifying_key_bytes.is_empty() {
            return Err(DatError::ParseDatVerifyingKeyError);
        }

        let verifying_key = UnparsedPublicKey::new(va, verifying_key_bytes);

        Ok(DatSignatureKey {
            algorithm,
            signing_key,
            signing_key_bytes,
            verifying_key,
        })
    }

    pub fn algorithm(&self) -> DatSignatureAlgorithm {
        self.algorithm
    }

    pub fn signature_size(&self) -> usize {
        match self.algorithm {
            DatSignatureAlgorithm::P256 => 64,
            DatSignatureAlgorithm::P384 => 96,
            DatSignatureAlgorithm::P521 => 132,
        }
    }

    pub fn raw_signing_key_size(&self) -> usize {
        match self.algorithm {
            DatSignatureAlgorithm::P256 => 32,
            DatSignatureAlgorithm::P384 => 48,
            DatSignatureAlgorithm::P521 => 66,
        }
    }

    pub fn to_bytes(&self) -> (Box<[u8]>, Box<[u8]>) {
        (Box::from(&*self.signing_key_bytes), Box::from(&*self.verifying_key.as_ref()))
    }

    pub fn sign(&self, data: &[u8]) -> Result<Box<[u8]>, DatError> {
        self.signing_key.as_ref().ok_or_else(|| DatError::VerifyOnlyKey)?
            .sign(&aws_lc_rs::rand::SystemRandom::new(), data)
            .map(|x| Box::from(x.as_ref()))
            .map_err(|_| DatError::DatSignatureError)
    }

    pub fn verify(&self, body: &[u8], sign: &[u8]) -> Result<(), DatError> {
        self.verifying_key.verify(body, sign).map_err(|_| DatError::InvalidDat)
    }

    pub fn has_signing_key(&self) -> bool {
        self.signing_key.is_some()
    }
}

impl Clone for DatSignatureKey {
    fn clone(&self) -> Self {
        let (k, v) = self.to_bytes();
        DatSignatureKey::from_bytes(self.algorithm(), &*k, &*v).unwrap()
    }
}

pub fn to_pkcs8_der(algorithm: DatSignatureAlgorithm, signing_key: &[u8]) -> Result<Vec<u8>, DatError> {
    if signing_key.is_empty() {
        return Ok(Vec::new());
    }

    // match algorithm {
    //     DatSignatureAlgorithm::P256 => {
    //         if signing_key.len() != 32 { return Err(DatError::ParseDatSigningKeyError); }
    //         // P-256용 고정 PKCS#8 헤더 (알고리즘 OID 및 구조 포함)
    //         let mut der = vec![
    //             0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce,
    //             0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x04,
    //             0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
    //         ];
    //         der.extend_from_slice(signing_key);
    //         // 추가적인 파라미터(공개키 등)가 생략된 최소형 PKCS#8
    //         Ok(der)
    //     },
    //     DatSignatureAlgorithm::P384 => {
    //         if signing_key.len() != 48 { return Err(DatError::ParseDatSigningKeyError); }
    //         let mut der = vec![
    //             0x30, 0x7a, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce,
    //             0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x04, 0x63, 0x30,
    //             0x61, 0x02, 0x01, 0x01, 0x04, 0x30,
    //         ];
    //         der.extend_from_slice(signing_key);
    //         Ok(der)
    //     },
    //     DatSignatureAlgorithm::P521 => {
    //         if signing_key.len() != 66 { return Err(DatError::ParseDatSigningKeyError); }
    //         // P-521은 전체 길이가 128을 넘으므로 0x81 형식의 길이 인코딩이 들어감
    //         let mut der = vec![
    //             0x30, 0x81, 0x8f, 0x02, 0x01, 0x00, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce,
    //             0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23, 0x04, 0x78, 0x30,
    //             0x76, 0x02, 0x01, 0x01, 0x04, 0x42,
    //         ];
    //         der.extend_from_slice(signing_key);
    //         Ok(der)
    //     },
    // }

    Ok(match algorithm {
        DatSignatureAlgorithm::P256 => {
            let k = p256::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?;
            p256::pkcs8::EncodePrivateKey::to_pkcs8_der(&k).map_err(|_| DatError::ParseDatSigningKeyError)?.as_bytes().to_vec()
        },
        DatSignatureAlgorithm::P384 => {
            let k = p384::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?;
            p384::pkcs8::EncodePrivateKey::to_pkcs8_der(&k).map_err(|_| DatError::ParseDatSigningKeyError)?.as_bytes().to_vec()
        },
        DatSignatureAlgorithm::P521 => {
            let k = p521::ecdsa::SigningKey::from_slice(signing_key).map_err(|_| DatError::ParseDatSigningKeyError)?;
            p521::pkcs8::EncodePrivateKey::to_pkcs8_der(&k).map_err(|_| DatError::ParseDatSigningKeyError)?.as_bytes().to_vec()
        },
    })
}

pub fn to_raw(algorithm: DatSignatureAlgorithm, pkcs8_der: &[u8]) -> Result<Vec<u8>, DatError> {
    if pkcs8_der.is_empty() {
        return Ok(Vec::new());
    }

    // let (oid, key_len) = match algorithm {
    //     DatSignatureAlgorithm::P256 => (vec![0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07], 32),
    //     DatSignatureAlgorithm::P384 => (vec![0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22], 48),
    //     DatSignatureAlgorithm::P521 => (vec![0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x23], 66),
    // };
    //
    // let oid_pos = pkcs8_der.windows(oid.len()).position(|w| w == oid)
    //     .ok_or_else(|| DatError::ParseDatSigningKeyError)?;
    //
    // let search_area = &pkcs8_der[oid_pos + oid.len()..];
    //
    // let tag_pattern = [0x04, key_len as u8];
    //
    // let key_pos = search_area.windows(2).position(|w| w == tag_pattern)
    //     .ok_or_else(|| DatError::ParseDatSigningKeyError)?;
    //
    // let start = oid_pos + oid.len() + key_pos + 2;
    // Ok(Vec::from(&pkcs8_der[start..start + key_len]))

    Ok(match algorithm {
        DatSignatureAlgorithm::P256 => {
            let k: p256::ecdsa::SigningKey = p256::pkcs8::DecodePrivateKey::from_pkcs8_der(pkcs8_der).map_err(|_| DatError::ParseDatSigningKeyError)?;
            k.to_bytes().to_vec()
        },
        DatSignatureAlgorithm::P384 => {
            let k: p384::ecdsa::SigningKey = p384::pkcs8::DecodePrivateKey::from_pkcs8_der(pkcs8_der).map_err(|_| DatError::ParseDatSigningKeyError)?;
            k.to_bytes().to_vec()
        },
        DatSignatureAlgorithm::P521 => {
            let k: p521::ecdsa::SigningKey = p521::pkcs8::DecodePrivateKey::from_pkcs8_der(pkcs8_der).map_err(|_| DatError::ParseDatSigningKeyError)?;
            k.to_bytes().to_vec()
        },
    })
}