Skip to content

Commit

Permalink
Fix PKCS1 handling (#929)
Browse files Browse the repository at this point in the history
* Support pkcs1 format keys.

* Test pkcs1 support.

* changelog

* rust formatting
  • Loading branch information
Half-Shot authored Apr 16, 2024
1 parent 4839340 commit ff20011
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
1 change: 1 addition & 0 deletions changelog.d/929.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Track which key was used to encrypt secrets in storage, and encrypt/decrypt secrets in Rust.
17 changes: 14 additions & 3 deletions src/tokens/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::string::FromUtf8Error;
use base64ct::{Base64, Encoding};
use napi::bindgen_prelude::Buffer;
use napi::Error;
use rsa::pkcs1::DecodeRsaPrivateKey;
use rsa::pkcs8::DecodePrivateKey;
use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey};

Expand All @@ -17,7 +18,9 @@ struct TokenEncryption {
#[allow(dead_code)]
enum TokenEncryptionError {
FromUtf8(FromUtf8Error),
PrivateKey(rsa::pkcs8::Error),
UnknownFormat,
PrivateKey8(rsa::pkcs8::Error),
PrivateKey1(rsa::pkcs1::Error),
}

#[derive(Debug)]
Expand All @@ -31,8 +34,16 @@ enum DecryptError {
impl TokenEncryption {
pub fn new(private_key_data: Vec<u8>) -> Result<Self, TokenEncryptionError> {
let data = String::from_utf8(private_key_data).map_err(TokenEncryptionError::FromUtf8)?;
let private_key = RsaPrivateKey::from_pkcs8_pem(data.as_str())
.map_err(TokenEncryptionError::PrivateKey)?;
let private_key: RsaPrivateKey;
if data.starts_with("-----BEGIN PRIVATE KEY-----") {
private_key = RsaPrivateKey::from_pkcs8_pem(data.as_str())
.map_err(TokenEncryptionError::PrivateKey8)?;
} else if data.starts_with("-----BEGIN RSA PRIVATE KEY-----") {
private_key = RsaPrivateKey::from_pkcs1_pem(data.as_str())
.map_err(TokenEncryptionError::PrivateKey1)?;
} else {
return Err(TokenEncryptionError::UnknownFormat);
}
let public_key = private_key.to_public_key();
Ok(TokenEncryption {
private_key,
Expand Down
21 changes: 21 additions & 0 deletions tests/tokens/tokenencryption.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { expect } from "chai";

describe("TokenEncryption", () => {
let keyPromise: Promise<Buffer>;
let keyPromisePKCS1: Promise<Buffer>;
async function createTokenEncryption() {
return new TokenEncryption(await keyPromise);
}
Expand All @@ -24,6 +25,21 @@ describe("TokenEncryption", () => {
} satisfies RSAKeyPairOptions<"pem", "pem">, (err, _, privateKey) => {
if (err) { reject(err) } else { resolve(Buffer.from(privateKey)) }
}));
keyPromisePKCS1 = new Promise<Buffer>((resolve, reject) => generateKeyPair("rsa", {
// Deliberately shorter length to speed up test
modulusLength: 2048,
privateKeyEncoding: {
type: "pkcs1",
format: "pem",
},
publicKeyEncoding: {
format: "pem",
type: "pkcs1",
}
} satisfies RSAKeyPairOptions<"pem", "pem">, (err, _, privateKey) => {
if (err) { reject(err) } else { resolve(Buffer.from(privateKey)) }
}));

}, );
it('should be able to encrypt a string into a single part', async() => {
const tokenEncryption = await createTokenEncryption();
Expand All @@ -45,4 +61,9 @@ describe("TokenEncryption", () => {
const result = tokenEncryption.decrypt(value);
expect(result).to.equal(plaintext);
});
it('should support pkcs1 format keys', async() => {
const tokenEncryption = new TokenEncryption(await keyPromisePKCS1);
const result = tokenEncryption.encrypt('hello world');
expect(result).to.have.lengthOf(1);
});
});

0 comments on commit ff20011

Please sign in to comment.