feat: add tests, add sshpubkey, sshprivkey, sshcert, sshbase

This commit is contained in:
2024-08-28 00:51:57 +08:00
parent 9f4dc1ef09
commit 2a0faa35cd
6 changed files with 117 additions and 9 deletions

View File

@@ -1 +1,5 @@
mod sshrw;
mod sshbase;
mod sshrw;
mod sshpubkey;
mod sshprivkey;
mod sshcert;

3
src/sshbase.rs Normal file
View File

@@ -0,0 +1,3 @@
use std::error::Error;
pub type SshResult<T> = Result<T, Box<dyn Error>>;

1
src/sshcert.rs Normal file
View File

@@ -0,0 +1 @@
pub struct SshCert {}

1
src/sshprivkey.rs Normal file
View File

@@ -0,0 +1 @@
pub struct SshPrivateKey {}

41
src/sshpubkey.rs Normal file
View File

@@ -0,0 +1,41 @@
use crate::sshbase::SshResult;
pub struct SshPubicKey {
pub algorithm: String,
pub value: SshPubicKeyValue,
pub comment: Option<String>,
}
pub enum SshPubicKeyValue {
Rsa(SshRsaPublicKeyValue),
Ecdsa(SshEcdsaPublicKeyValue),
Ed25519(SshEd25519PublicKeyValue),
}
pub struct SshRsaPublicKeyValue {
pub e: Vec<u8>,
pub n: Vec<u8>,
}
pub enum SshEcdsaPublicKeyAlgorithm {
Sha2NistP256,
Sha2NistP384,
Sha2NistP521,
}
pub struct SshEcdsaPublicKeyValue {
pub a: SshEcdsaPublicKeyAlgorithm,
pub p: String,
}
pub struct SshEd25519PublicKeyValue {
pub p: Vec<u8>,
}
impl SshPubicKey {
pub fn parse(key: &str) -> SshResult<Self> {
// TODO ...
Err("".to_string())?
}
}

View File

@@ -1,11 +1,7 @@
use crate::sshbase::SshResult;
use base64::Engine;
use std::error::Error;
use std::io::{Cursor, Read};
const ED25519_PK_SZ: u32 = 32;
pub type SshResult<T> = Result<T, Box<dyn Error>>;
pub struct SshReader {
buffer_len: usize,
read_len: usize,
@@ -43,6 +39,15 @@ impl SshReader {
}
}
pub fn read_big_num(&mut self) -> SshResult<Vec<u8>> {
let bn = self.read_string()?;
if bn.len() > 1 && bn[0] == 0 {
Ok(bn[1..].to_vec())
} else {
Ok(bn)
}
}
pub fn read_left(&mut self) -> SshResult<Vec<u8>> {
self.read_bytes(self.left_bytes() as u32)
}
@@ -59,12 +64,16 @@ pub struct SshWriter {
}
impl SshWriter {
pub fn new(bytes: Vec<u8>) -> Self {
pub fn new() -> Self {
Self {
buffer: bytes,
buffer: vec![],
}
}
pub fn as_slice(&self) -> &[u8] {
self.buffer.as_slice()
}
pub fn write_bytes(&mut self, bytes: &[u8]) {
self.buffer.extend_from_slice(bytes);
}
@@ -77,6 +86,17 @@ impl SshWriter {
self.write_u32(bytes.len() as u32);
self.write_bytes(bytes);
}
pub fn write_big_num(&mut self, bn: &[u8]) {
if (bn.len() > 0) && (bn[0] & 0x80 != 0) {
let mut buff = Vec::with_capacity(bn.len() + 1);
buff.push(0_u8);
buff.extend_from_slice(bn);
self.write_string(&buff);
} else {
self.write_string(bn);
}
}
}
#[test]
@@ -93,6 +113,28 @@ k/QQmZ2Nu29OYSWITbWcoeszsC+AmpFa9zhF/TG+iwmRFKlmodyCWU=";
let algorithm = ssh_reader.read_string().unwrap();
assert_eq!(b"ssh-rsa", algorithm.as_slice());
let e = ssh_reader.read_big_num().unwrap();
let n = ssh_reader.read_big_num().unwrap();
assert_eq!("010001", hex::encode(&e));
assert_eq!("bcda85520bae21bb91f76e9772646352f70ee227f9c5f2207a0187e99577403126690ea1ec18b\
7e38fcf2794981bea6242474bf536130d0d101c67854eff02e72df646dfce2d8296c4bae049b1adb56186af71\
d3c858a9e5865b8d47434f1aa3246bac8512b27dee23c469325974ad11d6270e63918d93bd672860d03f4ebc9\
7f1a11f4091c33644da002c7c0de496775bd4dd3048568d506ad56da45f19bfca5d02c918950fe859f4267000\
44d3288e16288093987c5ea3caa9dfca7e4d67113dccbff29021d908a5d9cdf44accd64c27935c0c386a91fa1\
3eda8adaf24cfdf5042417ca7964986df48052fa7fde791ff84130e554d49817478f1dcc6670944a09c5e6f7e\
51181cc1aee084485914e05cca8c5710c586ed8170bfe7398dd39bdba666776503bd0b04771110e990336f31e\
971771179dbd1308b78a81e5fb77c954c8e7675f0150690e9f46df547228bd7f7e269ea6870a24fd042667636\
edbd3984962136d67287accec0be026a456bdce117f4c6fa2c264452a59a87720965", hex::encode(&n));
assert_eq!(0, ssh_reader.left_bytes());
let mut ssh_writer = SshWriter::new();
ssh_writer.write_string(b"ssh-rsa");
ssh_writer.write_big_num(&e);
ssh_writer.write_big_num(&n);
assert_eq!(id_rsa_pub, STANDARD.encode(ssh_writer.as_slice()));
let id_rsa = "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn\
NhAAAAAwEAAQAAAYEAvNqFUguuIbuR926XcmRjUvcO4if5xfIgegGH6ZV3QDEmaQ6h7Bi3\
44/PJ5SYG+piQkdL9TYTDQ0QHGeFTv8C5y32Rt/OLYKWxLrgSbGttWGGr3HTyFip5YZbjU\
@@ -148,10 +190,19 @@ M9hkSeHxHrJ1+FMK2xNTd+LF17A/WW3YYTBCz8tQvhtgOQDiSk/9Lnc+vFlMF7LN0dwgwl4zIg07h0M=
assert_eq!(
"04bb03d7aa0f33d86449e1f11eb275f8530adb135377e2c5d7b03f596dd8613042cfcb50be1b603900e24a4\
ffd2e773ebc594c17b2cdd1dc20c25e33220d3b8743",
hex::encode(ecc_key_point));
hex::encode(&ecc_key_point));
assert_eq!(0, ssh_reader.left_bytes());
let mut ssh_writer = SshWriter::new();
ssh_writer.write_string(b"ecdsa-sha2-nistp256");
let mut ecc_key_blob_writer = SshWriter::new();
ecc_key_blob_writer.write_string(&ssh_algorithm);
ecc_key_blob_writer.write_string(&ecc_key_point);
ssh_writer.write_bytes(ecc_key_blob_writer.as_slice());
assert_eq!(id_ecdsa_pub, STANDARD.encode(ssh_writer.as_slice()));
let id_ecdsa = "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS\
1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQS7A9eqDzPYZEnh8R6ydfhTCtsTU3fi\
xdewP1lt2GEwQs/LUL4bYDkA4kpP/S53PrxZTBeyzdHcIMJeMyINO4dDAAAAuK3kG36t5B\"
@@ -170,11 +221,18 @@ fn test_ed25519() {
assert_eq!(b"ssh-ed25519", algorithm.as_slice());
let pub_key = ssh_reader.read_string().unwrap();
assert_eq!(32, pub_key.len());
assert_eq!("4c1c2f991eda6a910d7316337e155b8df633b7e30127ef014513bbb03b42acd6",
hex::encode(&pub_key));
assert_eq!(0, ssh_reader.left_bytes());
let mut ssh_writer = SshWriter::new();
ssh_writer.write_string(b"ssh-ed25519");
ssh_writer.write_string(&pub_key);
assert_eq!(id_ed25519_pub, STANDARD.encode(ssh_writer.as_slice()));
let id_ed25519 = "b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW\
QyNTUxOQAAACBMHC+ZHtpqkQ1zFjN+FVuN9jO34wEn7wFFE7uwO0Ks1gAAAKCwNsNtsDbD\
bQAAAAtzc2gtZWQyNTUxOQAAACBMHC+ZHtpqkQ1zFjN+FVuN9jO34wEn7wFFE7uwO0Ks1g\