I made a test with Azure JS SDK to use key vault to sign and verify data thanks to EC-HSM
when I use Azure JS SDK to verify it works correctly, I put the output in comments
describe('crypto services', () => {
it('Azure HSM', async () => {
const client = new KeyClient(
'https://xxx.vault.azure.net',
new EnvironmentCredential(),
);
const keys: { [key: string]: KeyVaultKey } = {};
for await (const key of client.listPropertiesOfKeys()) {
keys[key.name] = await client.getKey(key.name);
}
console.log('available keys', Object.keys(keys)); //logging ['tmp']
const cryptoClient = new CryptographyClient(
keys['tmp'],
new EnvironmentCredential(),
);
const content = Buffer.from('Hello world');
const sig = await cryptoClient.signData('ES256', content);
console.log('signature', Buffer.from(sig.result).toString('base64')); //logging different output on each call
console.log('key crv', keys['tmp'].key.crv); //P-256
console.log('key x', Buffer.from(keys['tmp'].key?.x).toString('base64')); //OC76WxZ/TMzJnRqv/cy9llDqSIMWlplgREY3jMxDCks=
console.log('key y', Buffer.from(keys['tmp'].key?.y).toString('base64')); //Dxgw8nqXoO3xXQruejfQa/Z+aFpo/4ilC64JUHoRoog=
const verif = await cryptoClient.verifyData('ES256', content, sig.result);
expect(verif.result).toBe(true);
});
})
Now, I'd like to verify locally without calling the azure sdk (which is exactly the reason to use asymmetric crypto in the first place)
it.only('local HSM verif', () => {
const content = Buffer.from('Hello world'); //same content
const sigs = [ //some values I received
'bxw1nS8Q39mnQVkAhvJctXuLHz4n0wUjLbE+phj1XlUeWDxl7DCK5bG4d7YrL7zGtAnUq3YT9AdrrAXjpwhCzQ==',
'hlh1CJSKivFYcdVygI0KJfUCGYor+whUu6NsJZhNTCllHHRmgh9FvcvxBSFVu0am7A9lryG/N5vLAv/B1Niiew==',
];
const base64X = 'OC76WxZ/TMzJnRqv/cy9llDqSIMWlplgREY3jMxDCks='; //same as output of previous test
const base64Y = 'Dxgw8nqXoO3xXQruejfQa/Z+aFpo/4ilC64JUHoRoog=';//same as output of previous test
//converting the jwk to PEM thanks to the jwk-to-pem package
const publicKey = jwkToPem({
kty: 'EC',
crv: 'P-256',
x: base64X,
y: base64Y,
});
for (const sig of sigs) {
const verifyLocal = crypto.createVerify('sha256');
verifyLocal.update(content);
const verifLocal = verifyLocal.verify(publicKey, sig);
expect(verifLocal).toBe(true); //it always fails here
}
});
Can someone explain what is going on ?
My guess is that the public signature is not correct, and so that x
and y
are not correct in base64
For ex, if I use mkjwk.org to generate a JWK
{
kty: 'EC',
d: '7LU9Y16XKiFMcPVm39B5fVOtG0s-bnJwaeEtMrk9udE',
crv: 'P-256',
x: 'g-68Nakmi41xMv6zKduBn4dqcqJ0KXDqdS2rFpxUQOA',
y: 'pYRqhl2YDKBwGGkIXdYQQWuNjOtPcCe1bz_VYalXFW0',
}
they seem shorter and without '/' or '='