Skip to content

Commit 5e90e90

Browse files
committed
Expose openpgp_sequoia::armor::Writer
Add an armor(bytes, ArmorKind) function Signed-off-by: Daniel Alley <dalley@redhat.com>
1 parent 3467270 commit 5e90e90

File tree

4 files changed

+75
-0
lines changed

4 files changed

+75
-0
lines changed

NEXT.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ New:
88
- Added `PacketPile` and `Packet` for low-level reading of individual packet fields [#61]
99
- Added `Sig.signature_type`, `Sig.hash_algorithm`, `Sig.key_algorithm`, and `Sig.key_validity_period` [#61]
1010
- Added `SignatureType`, `PublicKeyAlgorithm`, `HashAlgorithm`, `DataFormat`, `Tag` and `KeyFlags` as returned types [#61]
11+
- Added Sequoia's `armor::Writer` for applying Ascii Armor to data, via the `armor()` function and `ArmorKind` type [#61]
1112

1213
Changed:
1314
- `Sig.issuer_fpr` is now considered deprecated, use `Sig.issuer_fingerprint` instead [#60]

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,30 @@ assert packet.tag == Tag.PublicKey
692692
assert len(packet.body) > 0
693693
```
694694

695+
## ASCII armor
696+
697+
The `armor` function wraps raw binary OpenPGP data in ASCII armor,
698+
adding the appropriate header, base64 encoding, and CRC24 checksum:
699+
700+
```python
701+
from pysequoia import armor, ArmorKind
702+
703+
cert = Cert.generate("Test <test@example.com>")
704+
armored = armor(bytes(cert), ArmorKind.PublicKey)
705+
assert "-----BEGIN PGP PUBLIC KEY BLOCK-----" in armored
706+
assert "-----END PGP PUBLIC KEY BLOCK-----" in armored
707+
```
708+
709+
Other armor kinds are available for different data types:
710+
711+
```python
712+
armored_msg = armor(b"dummy data", ArmorKind.Message)
713+
assert "BEGIN PGP MESSAGE" in armored_msg
714+
715+
armored_sig = armor(b"dummy data", ArmorKind.Signature)
716+
assert "BEGIN PGP SIGNATURE" in armored_sig
717+
```
718+
695719
## License
696720

697721
This project is licensed under [Apache License, Version 2.0][APL].

src/lib.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ use sequoia_openpgp::parse::stream::GoodChecksum;
1919
use sequoia_openpgp::serialize::stream::Armorer;
2020
use sequoia_openpgp::serialize::{Marshal, stream::Message};
2121

22+
use crate::types::ArmorKind;
23+
2224
pub(crate) fn serialize<T>(p: Packet, armor_kind: T) -> sequoia_openpgp::Result<Vec<u8>>
2325
where
2426
T: Into<Option<Kind>>,
@@ -92,11 +94,32 @@ impl Decrypted {
9294
}
9395
}
9496

97+
/// Wrap raw OpenPGP data in ASCII armor.
98+
///
99+
/// Takes raw binary OpenPGP data and an `ArmorKind` specifying the armor
100+
/// header type, and returns the ASCII-armored string.
101+
#[pyfunction]
102+
pub fn armor(data: &[u8], kind: ArmorKind) -> PyResult<String> {
103+
let mut output = vec![];
104+
{
105+
let mut writer = sequoia_openpgp::armor::Writer::new(&mut output, kind.into())
106+
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e.to_string()))?;
107+
std::io::Write::write_all(&mut writer, data)
108+
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e.to_string()))?;
109+
writer
110+
.finalize()
111+
.map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e.to_string()))?;
112+
}
113+
String::from_utf8(output).map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e.to_string()))
114+
}
115+
95116
#[pymodule]
96117
pub mod pysequoia {
97118
#[pymodule_export]
98119
pub use super::Decrypted;
99120
#[pymodule_export]
121+
pub use super::armor;
122+
#[pymodule_export]
100123
pub use super::cert::Cert;
101124
#[pymodule_export]
102125
pub use super::cert::Profile;
@@ -127,6 +150,8 @@ pub mod pysequoia {
127150
#[pymodule_export]
128151
pub use super::signer::PySigner;
129152
#[pymodule_export]
153+
pub use super::types::ArmorKind;
154+
#[pymodule_export]
130155
pub use super::types::DataFormat;
131156
#[pymodule_export]
132157
pub use super::types::HashAlgorithm;

src/types.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,31 @@ impl TryFrom<SqTag> for Tag {
283283
}
284284
}
285285

286+
/// The type of ASCII armor to use when wrapping OpenPGP data.
287+
#[pyclass(eq)]
288+
#[derive(Clone, Copy, PartialEq, Eq)]
289+
pub enum ArmorKind {
290+
/// "PGP PUBLIC KEY BLOCK"
291+
PublicKey,
292+
/// "PGP PRIVATE KEY BLOCK"
293+
SecretKey,
294+
/// "PGP MESSAGE"
295+
Message,
296+
/// "PGP SIGNATURE"
297+
Signature,
298+
}
299+
300+
impl From<ArmorKind> for sequoia_openpgp::armor::Kind {
301+
fn from(kind: ArmorKind) -> Self {
302+
match kind {
303+
ArmorKind::PublicKey => Self::PublicKey,
304+
ArmorKind::SecretKey => Self::SecretKey,
305+
ArmorKind::Message => Self::Message,
306+
ArmorKind::Signature => Self::Signature,
307+
}
308+
}
309+
}
310+
286311
/// The key usage flags from an OpenPGP signature.
287312
///
288313
/// Indicates what operations a key is authorized to perform.

0 commit comments

Comments
 (0)