Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
maxtropets committed Aug 2, 2024
1 parent c9be3dd commit 1ca8797
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 30 deletions.
4 changes: 2 additions & 2 deletions js/ccf-app/src/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,15 @@ export interface CryptoKeyPair {
publicKey: string;
}

export type AlgorithmName = "RSASSA-PKCS1-v1_5" | "ECDSA" | "EdDSA" | "HMAC";
export type AlgorithmName = "RSASSA-PSS" | "ECDSA" | "EdDSA" | "HMAC";

export type DigestAlgorithm = "SHA-256" | "SHA-384" | "SHA-512";

export interface SigningAlgorithm {
name: AlgorithmName;

/**
* Digest algorithm. It's necessary for "RSASSA-PKCS1-v1_5", "ECDSA", and "HMAC"
* Digest algorithm. It's necessary for "RSASSA-PSS", "ECDSA", and "HMAC"
*/
hash?: DigestAlgorithm;
}
Expand Down
10 changes: 5 additions & 5 deletions js/ccf-app/src/polyfill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ class CCFPolyfill implements CCF {
let padding = undefined;
const privKey = jscrypto.createPrivateKey(key);
if (privKey.asymmetricKeyType == "rsa") {
if (algorithm.name === "RSASSA-PKCS1-v1_5") {
padding = jscrypto.constants.RSA_PKCS1_PADDING;
if (algorithm.name === "RSASSA-PSS") {
padding = jscrypto.constants.RSA_PKCS1_PSS_PADDING;
} else {
throw new Error("incompatible signing algorithm for given key type");
}
Expand Down Expand Up @@ -179,8 +179,8 @@ class CCFPolyfill implements CCF {
let padding = undefined;
const pubKey = jscrypto.createPublicKey(key);
if (pubKey.asymmetricKeyType == "rsa") {
if (algorithm.name === "RSASSA-PKCS1-v1_5") {
padding = jscrypto.constants.RSA_PKCS1_PADDING;
if (algorithm.name === "RSASSA-PSS") {
padding = jscrypto.constants.RSA_PKCS1_PSS_PADDING;
} else {
throw new Error("incompatible signing algorithm for given key type");
}
Expand Down Expand Up @@ -210,7 +210,7 @@ class CCFPolyfill implements CCF {
{
key: pubKey,
dsaEncoding: "ieee-p1363",
padding: padding,
padding: padding
},
new Uint8Array(signature),
);
Expand Down
21 changes: 11 additions & 10 deletions js/ccf-app/test/polyfill.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ describe("polyfill", function () {
});
});
describe("sign", function () {
it("performs RSASSA-PKCS1-v1_5 sign correctly", function () {
it("performs RSASSA-PSS sign correctly", function () {
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
modulusLength: 2048,
publicKeyEncoding: {
Expand All @@ -182,7 +182,7 @@ describe("polyfill", function () {
const data = ccf.strToBuf("foo");
const signature = ccf.crypto.sign(
{
name: "RSASSA-PKCS1-v1_5",
name: "RSASSA-PSS",
hash: "SHA-256",
},
privateKey,
Expand All @@ -198,6 +198,7 @@ describe("polyfill", function () {
{
key: publicKey,
dsaEncoding: "ieee-p1363",
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
},
new Uint8Array(signature),
),
Expand All @@ -208,7 +209,7 @@ describe("polyfill", function () {
assert.isTrue(
ccf.crypto.verifySignature(
{
name: "RSASSA-PKCS1-v1_5",
name: "RSASSA-PSS",
hash: "SHA-256",
},
publicKey,
Expand Down Expand Up @@ -392,20 +393,20 @@ describe("polyfill", function () {
});
});
describe("verifySignature", function () {
it("performs RSASSA-PKCS1-v1_5 validation correctly", function () {
it("performs RSASSA-PSS validation correctly", function () {
const { cert, publicKey, privateKey } = generateSelfSignedCert();
const signer = crypto.createSign("sha256");
const data = ccf.strToBuf("foo");
signer.update(new Uint8Array(data));
signer.end();
const signature = signer.sign({
key: crypto.createPrivateKey(privateKey),
padding: crypto.constants.RSA_PKCS1_PADDING,
padding: crypto.constants.RSA_PKCS1_PSS_PADDING,
});
assert.isTrue(
ccf.crypto.verifySignature(
{
name: "RSASSA-PKCS1-v1_5",
name: "RSASSA-PSS",
hash: "SHA-256",
},
cert,
Expand All @@ -416,7 +417,7 @@ describe("polyfill", function () {
assert.isTrue(
ccf.crypto.verifySignature(
{
name: "RSASSA-PKCS1-v1_5",
name: "RSASSA-PSS",
hash: "SHA-256",
},
publicKey,
Expand All @@ -427,7 +428,7 @@ describe("polyfill", function () {
assert.isNotTrue(
ccf.crypto.verifySignature(
{
name: "RSASSA-PKCS1-v1_5",
name: "RSASSA-PSS",
hash: "SHA-256",
},
cert,
Expand Down Expand Up @@ -494,7 +495,7 @@ describe("polyfill", function () {
assert.throws(() =>
ccf.crypto.verifySignature(
{
name: "RSASSA-PKCS1-v1_5",
name: "RSASSA-PSS",
hash: "SHA-256",
},
publicKey,
Expand Down Expand Up @@ -543,7 +544,7 @@ describe("polyfill", function () {
assert.throws(() =>
ccf.crypto.verifySignature(
{
name: "RSASSA-PKCS1-v1_5",
name: "RSASSA-PSS",
hash: "SHA-256",
},
publicKey,
Expand Down
1 change: 1 addition & 0 deletions src/crypto/openssl/rsa_key_pair.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ namespace ccf::crypto
auto hash = OpenSSLHashProvider().Hash(d.data(), d.size(), md_type);
Unique_EVP_PKEY_CTX pctx(key);
CHECK1(EVP_PKEY_sign_init(pctx));
CHECK1(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING));
CHECK1(EVP_PKEY_CTX_set_signature_md(pctx, get_md_type(md_type)));
size_t olen = r.size();
CHECK1(EVP_PKEY_sign(pctx, r.data(), &olen, hash.data(), hash.size()));
Expand Down
1 change: 1 addition & 0 deletions src/crypto/openssl/rsa_public_key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ namespace ccf::crypto
auto hash = OpenSSLHashProvider().Hash(contents, contents_size, md_type);
Unique_EVP_PKEY_CTX pctx(key);
CHECK1(EVP_PKEY_verify_init(pctx));
CHECK1(EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING));
CHECK1(EVP_PKEY_CTX_set_signature_md(pctx, get_md_type(md_type)));
return EVP_PKEY_verify(
pctx, signature, signature_size, hash.data(), hash.size()) == 1;
Expand Down
21 changes: 13 additions & 8 deletions src/js/extensions/ccf/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ namespace ccf::js::extensions
sig_der, key_pair->get_curve_id());
return JS_NewArrayBufferCopy(ctx, sig.data(), sig.size());
}
else if (algo_name == "RSASSA-PKCS1-v1_5")
else if (algo_name == "RSASSA-PSS")
{
auto key_pair = ccf::crypto::make_rsa_key_pair(key);
auto sig = key_pair->sign(contents, mdtype);
Expand All @@ -900,8 +900,8 @@ namespace ccf::js::extensions
{
return JS_ThrowRangeError(
ctx,
"Unsupported signing algorithm, supported: RSASSA-PKCS1-v1_5, "
"ECDSA, EdDSA, HMAC");
"Unsupported signing algorithm, supported: RSASSA-PSS, ECDSA, "
"EdDSA, HMAC");
}
}
catch (const std::exception& ex)
Expand Down Expand Up @@ -1010,12 +1010,12 @@ namespace ccf::js::extensions
ctx, "Unsupported hash algorithm, supported: SHA-256");
}

if (algo_name != "RSASSA-PKCS1-v1_5" && algo_name != "ECDSA")
if (algo_name != "RSASSA-PSS" && algo_name != "ECDSA")
{
return JS_ThrowRangeError(
ctx,
"Unsupported signing algorithm, supported: RSASSA-PKCS1-v1_5, "
"ECDSA, EdDSA");
"Unsupported signing algorithm, supported: RSASSA-PSS, ECDSA, "
"EdDSA");
}

std::vector<uint8_t> sig(signature, signature + signature_size);
Expand All @@ -1035,13 +1035,18 @@ namespace ccf::js::extensions
valid =
verifier->verify(data, data_size, sig.data(), sig.size(), mdtype);
}
else
else if (algo_name == "ECDSA")
{
auto public_key = ccf::crypto::make_public_key(key);
valid =
public_key->verify(data, data_size, sig.data(), sig.size(), mdtype);
}

else
{
auto public_key = ccf::crypto::make_rsa_public_key(key);
valid =
public_key->verify(data, data_size, sig.data(), sig.size(), mdtype);
}
return JS_NewBool(ctx, valid);
}
catch (const std::exception& ex)
Expand Down
21 changes: 18 additions & 3 deletions tests/infra/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,15 @@ def sign(algorithm: dict, key_pem: str, data: bytes) -> bytes:
else:
raise ValueError("Unsupported hash algorithm")
if isinstance(key, rsa.RSAPrivateKey):
if algorithm["name"] == "RSASSA-PKCS1-v1_5":
return key.sign(data, padding.PKCS1v15(), hash_alg)
if algorithm["name"] == "RSASSA-PSS":
return key.sign(
data,
padding=padding.PSS(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH,
),
algorithm=hash_alg,
)
else:
raise ValueError("Unsupported signing algorithm")
elif isinstance(key, ec.EllipticCurvePrivateKey):
Expand Down Expand Up @@ -254,7 +261,15 @@ def verify_signature(algorithm: dict, signature: bytes, data: bytes, key_pub_pem
if isinstance(key_pub, rsa.RSAPublicKey):
if algorithm["hash"] != "SHA-256":
raise ValueError("Unsupported hash algorithm")
key_pub.verify(signature, data, padding.PKCS1v15(), hashes.SHA256())
key_pub.verify(
signature,
data,
padding.PSS(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH,
),
hashes.SHA256(),
)
elif isinstance(key_pub, ec.EllipticCurvePublicKey):
if algorithm["hash"] != "SHA-256":
raise ValueError("Unsupported hash algorithm")
Expand Down
4 changes: 2 additions & 2 deletions tests/npm_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ def test_npm_app(network, args):

# Test RSA signing + verification
key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048)
algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"}
algorithm = {"name": "RSASSA-PSS", "hash": "SHA-256"}
data = rand_bytes(random.randint(2, 50))
r = c.post(
"/app/sign",
Expand Down Expand Up @@ -551,7 +551,7 @@ def test_npm_app(network, args):
pass

key_priv_pem, key_pub_pem = infra.crypto.generate_rsa_keypair(2048)
algorithm = {"name": "RSASSA-PKCS1-v1_5", "hash": "SHA-256"}
algorithm = {"name": "RSASSA-PSS", "hash": "SHA-256"}
signature = infra.crypto.sign(algorithm, key_priv_pem, data)
r = c.post(
"/app/verifySignature",
Expand Down

0 comments on commit 1ca8797

Please sign in to comment.