gix_object/signature/
mod.rs1use std::ops::Range;
4
5use bstr::{BStr, BString, ByteSlice};
6
7#[cfg(feature = "signature")]
9pub mod sign;
10#[cfg(feature = "signature")]
12pub mod verify;
13
14#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct SignatureRef<'a> {
17 pub format: Format,
19 pub data: &'a BStr,
21}
22
23#[derive(PartialEq, Eq, Debug, Hash, Clone)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
26pub struct SignedData<'a> {
27 data: &'a [u8],
28 excluded: Range<usize>,
29}
30
31impl<'a> SignedData<'a> {
32 pub(crate) fn new(data: &'a [u8], excluded: Range<usize>) -> Self {
33 SignedData { data, excluded }
34 }
35
36 pub(crate) fn segments(&self) -> [&[u8]; 2] {
37 [&self.data[..self.excluded.start], &self.data[self.excluded.end..]]
38 }
39
40 pub fn to_bstring(&self) -> BString {
42 let [before, after] = self.segments();
43 let mut out = BString::from(before);
44 out.extend_from_slice(after);
45 out
46 }
47}
48
49impl From<SignedData<'_>> for BString {
50 fn from(value: SignedData<'_>) -> Self {
51 value.to_bstring()
52 }
53}
54
55pub(crate) fn find(data: &[u8]) -> Option<(usize, Format)> {
57 let mut found = None;
58 let mut offset = 0;
59 while offset < data.len() {
60 if let Some(format) = Format::from_signature(&data[offset..]) {
61 found = Some((offset, format));
62 }
63 offset = data[offset..]
64 .find_byte(b'\n')
65 .map_or(data.len(), |newline| offset + newline + 1);
66 }
67 found
68}
69
70#[derive(Clone, Copy, Debug, Eq, PartialEq)]
72pub enum Format {
73 OpenPgp,
75 X509,
77 Ssh,
79}
80
81impl Format {
82 pub fn from_signature(signature: &[u8]) -> Option<Self> {
84 if signature.starts_with(b"-----BEGIN PGP SIGNATURE-----")
85 || signature.starts_with(b"-----BEGIN PGP MESSAGE-----")
86 {
87 Some(Format::OpenPgp)
88 } else if signature.starts_with(b"-----BEGIN SIGNED MESSAGE-----") {
89 Some(Format::X509)
90 } else if signature.starts_with(b"-----BEGIN SSH SIGNATURE-----") {
91 Some(Format::Ssh)
92 } else {
93 None
94 }
95 }
96}