Closed the-unreal-adi closed 1 week ago
If you use SHA256 in your verification side maybe you should use Mechanism(CKM_SHA256_RSA_PKCS, None)
for the signature, instead of PyKCS11.MechanismRSAPKCS1
I started with Mechanism(CKM_SHA256_RSA_PKCS, None). Here's what I did, I first hashed the data using sha256 and then signed it using Mechanism(CKM_SHA256_RSA_PKCS, None). It didn't work out. I read somewhere that if we are prehashing the data then we should use Mechanism(CKM_RSA_PKCS, None). Then I read in your documentation that use PyKCS11.MechanismRSAPKCS1 for Mechanism(CKM_RSA_PKCS, None), that's why I am using PyKCS11.MechanismRSAPKCS1. I have tried every permutation and combination, in every case signature is being verified using PyKCS11 library but verification is failing if I use cryptography library.
Here's how I am fetching certificate and public key in PKCS11 for verification.
def fetch_certificate_publicKey_ownerName(session):
certs = session.findObjects([(PyKCS11.CKA_CLASS, PyKCS11.CKO_CERTIFICATE)])
if not certs:
raise ValueError("No certificate found on the DSC token")
cert_der = bytes(session.getAttributeValue(certs[0], [PyKCS11.CKA_VALUE], True)[0])
certificate = x509.load_der_x509_certificate(cert_der, default_backend())
public_key = certificate.public_key()
public_key_der = public_key.public_bytes(encoding=serialization.Encoding.DER, format=serialization.PublicFormat.SubjectPublicKeyInfo)
owner_name = certificate.subject.get_attributes_for_oid(x509.NameOID.COMMON_NAME)[0].value
return cert_der, public_key_der, owner_name
Do not hash before you sign.
Thanks this finally worked for me...
Signing
import os
from cryptography.hazmat.primitives import hashes
from PyKCS11 import *
# Path to your PKCS#11 library
PKCS11_LIB_PATH = "eps2003csp11v264.dll" # Replace with your PKCS#11 library path
# Data to be signed
data = b"ilovepython"
data2 = b"iloveupython"
# Step 1: Compute the hash of the data
def compute_hash(data, algorithm=hashes.SHA256):
hash_obj = hashes.Hash(algorithm(), backend=None)
hash_obj.update(data)
return hash_obj.finalize()
digest = compute_hash(data)
digest2 = compute_hash(data2)
pkcs11 = PyKCS11Lib()
pkcs11.load(PKCS11_LIB_PATH)
# Open session and login
slot = pkcs11.getSlotList(tokenPresent=True)[0]
session = pkcs11.openSession(slot)
session.login("0") # Replace with your token PIN
certs = session.findObjects([(PyKCS11.LowLevel.CKA_CLASS, PyKCS11.LowLevel.CKO_CERTIFICATE)])
if not certs:
raise ValueError("No certificate found on the DSC token")
cert_der = bytes(session.getAttributeValue(certs[0], [PyKCS11.LowLevel.CKA_VALUE], True)[0])
# Find the private key
priv_keys = session.findObjects([(PyKCS11.LowLevel.CKA_CLASS, PyKCS11.LowLevel.CKO_PRIVATE_KEY)])
if not priv_keys:
raise ValueError("No private key found on the DSC token")
priv_key = priv_keys[0]
# Perform raw RSA signing
signature = bytes(session.sign(priv_key, data, PyKCS11.Mechanism(PyKCS11.CKM_SHA256_RSA_PKCS)))
pub_keys = session.findObjects([(PyKCS11.LowLevel.CKA_CLASS, PyKCS11.LowLevel.CKO_PUBLIC_KEY)])
if not pub_keys:
raise ValueError("No public found on the DSC token")
pub_key = pub_keys[0]
result=session.verify(pub_key,data,signature,PyKCS11.Mechanism(PyKCS11.CKM_SHA256_RSA_PKCS))
print("Certificate: ", cert_der.hex())
print("Signature (hex): ", signature.hex())
print("Verified",result)
# Logout and close session
session.logout()
session.closeSession()
Verification
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.backends import default_backend
import binascii
# Public key in DER format (hexadecimal)
PUBLIC_KEY_DER_HEX = (
"30820122300d06092a864886f70d01010105000382010f003082010a02820101009a5f273b913292f10381be4d2a1e3a88cb24575b5d9c7792b7ff07d7e92e720c3ef139c4a830e3114799a3b1959838bd9a13b673df04e9f98699d5d4628662256209ac734f6d4870ef8473e2089fd3a4633f999c72397b060fd031d682f698ba4c6f4bf8393621422a2ce91aad21375d0b2fcd03ed9b4ddb5731011c50bb5a9fea2c3755bf07f1d6e53e76b337ddeb51228fa443bc6f09ffddca4cb0db8a751699e93688449c98d57ddaf2c5742dd8a2b085c8ed93f8cf1b7d45342168e028876a2e3be580b7af7840283250289f0e728b24bbc1cbd4f64ee6dcfac4dbff48c084df13aaa9fdc775b77c73734d63249010928160a296364539b94e7fe86470bf0203010001"
)
# Data to verify
data = b"ilovepython"
# Signature in hexadecimal format
SIGNATURE_HEX = (
"6d9f3e29c4e7ed9925dfd614dd66c717322945d9355d9631b1594d41f15cb31c645aa5fd8f667258fdca015873a983c1311b2e07c4fcab1cd3c8774b2883b71506cf76bf07e8bd3a7765661b46313a58eaf3d73ea1b40270337d0652bd1327a0d93541621924f117804143c8a93d5bc07b66ec9d134cbdbb9cc1f4b310f8b4bfc9ba0eb9356c0d2fbbb8872358eeed90338c2d72db94e9b2b4419beb51c74aa6cd5bffa607c30616df8a4ab096cf5015fb7bf72fa5d59b00b587e848ed38bcaee2c5183aa68a6f1cd60eaa276cb221c7746fa17fd5ee74f022555a3a2347dbccbd75d463c340d6144b2c2894e6d79f5da6df2c99a8ad0b18a27db32b16067c0d"
)
def load_public_key_from_der_hex(der_hex):
"""
Load a public key from DER format (hexadecimal string).
"""
public_key_der = binascii.unhexlify(der_hex)
return serialization.load_der_public_key(public_key_der, backend=default_backend())
def verify_raw_rsa_signature(public_key, data, signature):
"""
Verify an RSA signature with no padding (raw RSA operation).
"""
try:
# Compute the hash of the original data
hash_obj = hashes.Hash(hashes.SHA256(), backend=default_backend())
hash_obj.update(data)
digest = hash_obj.finalize()
# Log the hash (digest) and signature
print("Hash (digest):", digest.hex())
print("Signature (decoded):", signature.hex())
# Perform raw RSA verification
public_key.verify(
signature,
data, # Hash of the data
padding=padding.PKCS1v15(), # PKCS#1 v1.5 padding
algorithm=hashes.SHA256() # Explicitly specify the hash algorithm
)
print("Signature is valid.")
except Exception as e:
print(f"Signature verification failed: {e}")
# Main execution
if __name__ == "__main__":
# Load the public key from DER hexadecimal
public_key = load_public_key_from_der_hex(PUBLIC_KEY_DER_HEX)
# Decode the signature from hex
signature = binascii.unhexlify(SIGNATURE_HEX)
# Verify the signature
verify_raw_rsa_signature(public_key, data, signature)
Although I was wondering can we handle data hashing on our own and just sign the data without internal hashing...
Also I don't want to hardcode the pin and want to use dsc token prompt, can we do that here?
Thanks this finally worked for me...
Good!
Although I was wondering can we handle data hashing on our own and just sign the data without internal hashing...
You can sign the hash if you want to hash yourself. But the signature will also involve its own hash step.
Also I don't want to hardcode the pin and want to use dsc token prompt, can we do that here?
What is "dsc token prompt"?
Your system information
Please describe your issue in as much detail as possible:
I am creating a data signing module which will sign data using inserted DSC token. I am able to sign the data and verify signature using PyKCS11 library. But when I am trying to verify the signature using python cryptography module, I am getting verification failure.
Sharing the code
Verification code
Please let me know where I am getting wrong? I am also getting verification failure using openssl.