yggdrasil/src/util/signing.rs

91 lines
2.8 KiB
Rust

/*
* Yggdrasil: Minecraft authentication server
* Copyright (C) 2023 0xf8.dev@proton.me
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::fs::{read, read_to_string, try_exists, write};
use anyhow::Result;
use rsa::{
Oaep,
pkcs1::DecodeRsaPublicKey,
pkcs1::LineEnding,
pkcs1v15,
pkcs1v15::SigningKey,
pkcs8::{EncodePrivateKey, EncodePublicKey},
pkcs8::DecodePrivateKey,
RsaPrivateKey,
RsaPublicKey,
signature::{SignatureEncoding, Signer}
};
use crate::Config;
#[derive(Debug, Clone)]
pub struct Signing {
private: RsaPrivateKey,
pub public: RsaPublicKey,
pub signing: SigningKey<sha2::Sha256>
}
impl Signing {
pub fn init(config: &Config) -> Result<Self> {
Self::ensure(config)
}
fn ensure(config: &Config) -> Result<Self> {
if config.key_publ_location.try_exists()? && config.key_priv_location.try_exists()? {
Self::load(config)
} else {
Self::new(config)
}
}
fn new(config: &Config) -> Result<Self> {
let mut rng = rand::thread_rng();
let private = RsaPrivateKey::new(&mut rng, 4096).expect("Couldn't generate rsa key");
let public = RsaPublicKey::from(&private);
let signing = SigningKey::<sha2::Sha256>::new(private.to_owned());
let signing = Self { private, public, signing };
signing.save(config)?;
Ok(signing)
}
fn load(config: &Config) -> Result<Self> {
let private = DecodePrivateKey::read_pkcs8_der_file(config.key_priv_location.to_owned())?;
let public = DecodeRsaPublicKey::read_pkcs1_pem_file(config.key_publ_location.to_owned())?;
let signing = SigningKey::<sha2::Sha256>::new(private.to_owned());
Ok(Self { private, public, signing })
}
pub fn save(&self, config: &Config) -> Result<()> {
let der = self.private.to_pkcs8_der()?;
der.write_der_file(config.key_priv_location.to_owned())?;
let pem = self.public.to_public_key_pem(LineEnding::LF)?;
write(config.key_publ_location.to_owned(), pem)?;
Ok(())
}
pub fn sign(&self, data: &[u8]) -> Result<Vec<u8>> {
// let pad = Pss::new();
// Ok(self.private.sign(pad, data)?)
// Ok(self.signing)
todo!()
}
}