Skip to content

Commit ff20011

Browse files
authored
Fix PKCS1 handling (#929)
* Support pkcs1 format keys. * Test pkcs1 support. * changelog * rust formatting
1 parent 4839340 commit ff20011

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

changelog.d/929.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Track which key was used to encrypt secrets in storage, and encrypt/decrypt secrets in Rust.

src/tokens/mod.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::string::FromUtf8Error;
33
use base64ct::{Base64, Encoding};
44
use napi::bindgen_prelude::Buffer;
55
use napi::Error;
6+
use rsa::pkcs1::DecodeRsaPrivateKey;
67
use rsa::pkcs8::DecodePrivateKey;
78
use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};
89

@@ -17,7 +18,9 @@ struct TokenEncryption {
1718
#[allow(dead_code)]
1819
enum TokenEncryptionError {
1920
FromUtf8(FromUtf8Error),
20-
PrivateKey(rsa::pkcs8::Error),
21+
UnknownFormat,
22+
PrivateKey8(rsa::pkcs8::Error),
23+
PrivateKey1(rsa::pkcs1::Error),
2124
}
2225

2326
#[derive(Debug)]
@@ -31,8 +34,16 @@ enum DecryptError {
3134
impl TokenEncryption {
3235
pub fn new(private_key_data: Vec<u8>) -> Result<Self, TokenEncryptionError> {
3336
let data = String::from_utf8(private_key_data).map_err(TokenEncryptionError::FromUtf8)?;
34-
let private_key = RsaPrivateKey::from_pkcs8_pem(data.as_str())
35-
.map_err(TokenEncryptionError::PrivateKey)?;
37+
let private_key: RsaPrivateKey;
38+
if data.starts_with("-----BEGIN PRIVATE KEY-----") {
39+
private_key = RsaPrivateKey::from_pkcs8_pem(data.as_str())
40+
.map_err(TokenEncryptionError::PrivateKey8)?;
41+
} else if data.starts_with("-----BEGIN RSA PRIVATE KEY-----") {
42+
private_key = RsaPrivateKey::from_pkcs1_pem(data.as_str())
43+
.map_err(TokenEncryptionError::PrivateKey1)?;
44+
} else {
45+
return Err(TokenEncryptionError::UnknownFormat);
46+
}
3647
let public_key = private_key.to_public_key();
3748
Ok(TokenEncryption {
3849
private_key,

tests/tokens/tokenencryption.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { expect } from "chai";
44

55
describe("TokenEncryption", () => {
66
let keyPromise: Promise<Buffer>;
7+
let keyPromisePKCS1: Promise<Buffer>;
78
async function createTokenEncryption() {
89
return new TokenEncryption(await keyPromise);
910
}
@@ -24,6 +25,21 @@ describe("TokenEncryption", () => {
2425
} satisfies RSAKeyPairOptions<"pem", "pem">, (err, _, privateKey) => {
2526
if (err) { reject(err) } else { resolve(Buffer.from(privateKey)) }
2627
}));
28+
keyPromisePKCS1 = new Promise<Buffer>((resolve, reject) => generateKeyPair("rsa", {
29+
// Deliberately shorter length to speed up test
30+
modulusLength: 2048,
31+
privateKeyEncoding: {
32+
type: "pkcs1",
33+
format: "pem",
34+
},
35+
publicKeyEncoding: {
36+
format: "pem",
37+
type: "pkcs1",
38+
}
39+
} satisfies RSAKeyPairOptions<"pem", "pem">, (err, _, privateKey) => {
40+
if (err) { reject(err) } else { resolve(Buffer.from(privateKey)) }
41+
}));
42+
2743
}, );
2844
it('should be able to encrypt a string into a single part', async() => {
2945
const tokenEncryption = await createTokenEncryption();
@@ -45,4 +61,9 @@ describe("TokenEncryption", () => {
4561
const result = tokenEncryption.decrypt(value);
4662
expect(result).to.equal(plaintext);
4763
});
64+
it('should support pkcs1 format keys', async() => {
65+
const tokenEncryption = new TokenEncryption(await keyPromisePKCS1);
66+
const result = tokenEncryption.encrypt('hello world');
67+
expect(result).to.have.lengthOf(1);
68+
});
4869
});

0 commit comments

Comments
 (0)