I have been using software-protected RSA keys for testing and debugging in OCI Vault.
There seems to be a problem with SHA_256_RSA_PKCS1_V1_5 signatures generated from software-protected RSA keys when a DIGEST is provided, in that the signatures do not contain the expected ASN.1 DigestInfo wrapping as specified in RFC 2313 / 8017. (I tried providing the DigestInfo explicitly, but the /sign endpoint will only accept a raw 256-bit / 32-byte digest).
HSM-protected keys seem to work correctly, as do RAW (<245 byte) message signatures with software-protected keys.
To reproduce:
vault_digestinfo_issue_demo.bash:
#! /bin/bash
echo "Signing 'Hello world' with Soft and HSM Keys:"
/usr/bin/env python << \\EOF
import json
import base64
import hashlib
import requests
from oci.config import from_file
from oci.signer import Signer
def get_auth_session(profile_name='DEFAULT'):
#get config from file - ~/.oci/config
config = from_file(profile_name=profile_name)
auth = Signer(
tenancy = config['tenancy'],
user = config['user'],
fingerprint = config['fingerprint'],
private_key_file_location = config['key_file'],
pass_phrase = config['pass_phrase']
)
session = requests.Session()
session.auth=auth
return session
def write_raw(data,filename):
if isinstance(data, str):
mode="w"
else:
mode="wb"
file = open(filename, mode)
file.write(data)
file.close
def get_current_pubkey(s, key_id, vault_id, filename_prefix):
mastkey_info_url = mgmt_endpoint+"/20180608/keys/"+key_id
mastkey_info_resp = s.get(mastkey_info_url)
mastkey_info = mastkey_info_resp.json()
current_key_version_id = mastkey_info['currentKeyVersion']
current_key_version_url = mastkey_info_url+"/keyVersions/"+current_key_version_id
current_key_version_resp = s.get(current_key_version_url)
current_key_version = current_key_version_resp.json()
pubkey = current_key_version['publicKey']
write_raw(pubkey, filename_prefix+"-public-key.pem")
def vault_sign_digest(s, message, key_id, filename_prefix):
msg_hash = hashlib.sha256(message)
msg_digest = msg_hash.digest()
write_raw(msg_digest, filename_prefix+"-digest.dat")
msg_digest_b64 = base64.b64encode(msg_digest).decode('UTF-8')
sign_req = {
"keyId" : key_id,
"message" : msg_digest_b64,
"messageType" : 'DIGEST',
"signingAlgorithm" : 'SHA_256_RSA_PKCS1_V1_5'
}
sign_resp = s.post(sig_endpoint, json=sign_req)
sigb64 = sign_resp.json()['signature']
signature = base64.b64decode(sigb64)
write_raw(signature, filename_prefix+"-signature.dat")
############ PYTHON MAIN ###############
crypto_endpoint = "https://<REDACTED 1>-crypto.kms.ap-sydney-1.oraclecloud.com"
mgmt_endpoint = "https://<REDACTED 1>-management.kms.ap-sydney-1.oraclecloud.com"
sig_endpoint = crypto_endpoint+"/20180608/sign"
vault_ocid = "ocid1.vault.oc1.ap-sydney-1.<REDACTED 2>"
sftkey_ocid = "ocid1.key.oc1.ap-sydney-1.<REDACTED 2>"
hsmkey_ocid = "ocid1.key.oc1.ap-sydney-1.<REDACTED 2>"
message = b"Hello world"
s=get_auth_session()
get_current_pubkey(s, sftkey_ocid, vault_ocid, "soft")
get_current_pubkey(s, hsmkey_ocid, vault_ocid, "hsm")
vault_sign_digest(s, message, sftkey_ocid, "soft")
vault_sign_digest(s, message, hsmkey_ocid, "hsm")
\EOF
############ BASH MAIN ###############
for prefix in hsm soft
do
echo "Verifying $prefix key signature with openssl ..."
openssl rsautl -verify -pubin -inkey $prefix-public-key.pem -in $prefix-signature.dat > $prefix-verified-signature.der
echo
echo "$prefix key original sha256 message digest:"
od -t xC $prefix-digest.dat
echo
echo "$prefix key signature verification output (digest should be at byte 20 following DigestInfo):"
od -t xC $prefix-verified-signature.der
echo
echo "ASN.1 parsing $prefix key signature's DigestInfo structure:"
if openssl asn1parse -in $prefix-verified-signature.der -inform der
then
printf '\n DigestInfo OK \n\n'
else
printf '\n DigestInfo invalid or absent \n\n'
fi
echo "==========================================="
done
This produces:
$ ./vault_digestinfo_issue_demo.bash
Signing 'Hello world' with Soft and HSM Keys:
Verifying hsm key signature with openssl ...
hsm key original sha256 message digest:
0000000 64 ec 88 ca 00 b2 68 e5 ba 1a 35 67 8a 1b 53 16
0000020 d2 12 f4 f3 66 b2 47 72 32 53 4a 8a ec a3 7f 3c
0000040
hsm key signature verification output (digest should be at byte 20 following DigestInfo):
0000000 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05
0000020 00 04 20 64 ec 88 ca 00 b2 68 e5 ba 1a 35 67 8a
0000040 1b 53 16 d2 12 f4 f3 66 b2 47 72 32 53 4a 8a ec
0000060 a3 7f 3c
0000063
ASN.1 parsing of hsm key signature's DigestInfo structure:
0:d=0 hl=2 l= 49 cons: SEQUENCE
2:d=1 hl=2 l= 13 cons: SEQUENCE
4:d=2 hl=2 l= 9 prim: OBJECT :sha256
15:d=2 hl=2 l= 0 prim: NULL
17:d=1 hl=2 l= 32 prim: OCTET STRING [HEX DUMP]:64EC88CA00B268E5BA1A35678A1B5316D212F4F366B2477232534A8AECA37F3C
DigestInfo OK
===========================================
Verifying soft key signature with openssl ...
soft key original sha256 message digest:
0000000 64 ec 88 ca 00 b2 68 e5 ba 1a 35 67 8a 1b 53 16
0000020 d2 12 f4 f3 66 b2 47 72 32 53 4a 8a ec a3 7f 3c
0000040
soft key signature verification output (digest should be at byte 20 following DigestInfo):
0000000 64 ec 88 ca 00 b2 68 e5 ba 1a 35 67 8a 1b 53 16
0000020 d2 12 f4 f3 66 b2 47 72 32 53 4a 8a ec a3 7f 3c
0000040
ASN.1 parsing soft key signature's DigestInfo structure:
Error in encoding
8414759936:error:0DFFF07B:asn1 encoding routines:CRYPTO_internal:header too long:/AppleInternal/Library/BuildRoots/91a344b1-f985-11ee-b563-fe8bc7981bff/Library/Caches/com.apple.xbs/Sources/libressl/libressl-3.3/crypto/asn1/asn1_lib.c:152:
DigestInfo invalid or absent
===========================================
Is anyone else able to confirm this as a general problem?
Thanks!