Tcl
Tcl
ECDSA Sign and Verify
See more ECC Examples
Demonstrates how to create an ECDSA signature on the SHA256 hash of some data, and then verify.Chilkat Tcl Downloads
load ./chilkat.dll
set success 0
# This example assumes the Chilkat API to have been previously unlocked.
# See Global Unlock Sample for sample code.
# First load an ECDSA private key to be used for signing.
set privKey [new_CkPrivateKey]
set success [CkPrivateKey_LoadEncryptedPemFile $privKey "qa_data/ecc/secp256r1-key-pkcs8-secret.pem" "secret"]
if {$success == 0} then {
puts [CkPrivateKey_lastErrorText $privKey]
delete_CkPrivateKey $privKey
exit
}
# Sign the SHA256 hash of some data.
set bd [new_CkBinData]
set success [CkBinData_LoadFile $bd "qa_data/hamlet.xml"]
if {$success == 0} then {
puts "Failed to load file to be hashed."
delete_CkPrivateKey $privKey
delete_CkBinData $bd
exit
}
set crypt [new_CkCrypt2]
CkCrypt2_put_HashAlgorithm $crypt "sha256"
CkCrypt2_put_EncodingMode $crypt "base64"
set hashStr [CkCrypt2_hashBdENC $crypt $bd]
set ecdsa [new_CkEcc]
set prng [new_CkPrng]
# Returns ASN.1 signature as a base64 string.
set sig [CkEcc_signHashENC $ecdsa $hashStr "base64" $privKey $prng]
puts "sig = $sig"
# The signature is in ASN.1 format (which may be described as the "encoded DSS signature").
# SEQUENCE (2 elem)
# INTEGER (255 bit) 4849395540832462044300553275435608522154141569743642905628579547100940...
# INTEGER (255 bit) 3680701124244788134409868118208591399799457104230118295614152238560005...
# If you wish, you can get the r and s components of the signature like this:
set asn [new_CkAsn]
CkAsn_LoadEncoded $asn $sig "base64"
set xml [new_CkXml]
CkXml_LoadXml $xml [CkAsn_asnToXml $asn]
puts [CkXml_getXml $xml]
# We now have this:
# <?xml version="1.0" encoding="utf-8"?>
# <sequence>
# <int>6650D422D86BA4A228B5617604E59052591B9B2C32EF324C44D09EF67E5F0060</int>
# <int>0CFD9F6AC85042FC70F672C141BA6B2A4CAFBB906C3D907BCCC1BED62B28326F</int>
# </sequence>
# Get the "r" and "s" as hex strings
set r [CkXml_getChildContentByIndex $xml 0]
set s [CkXml_getChildContentByIndex $xml 1]
puts "r = $r"
puts "s = $s"
# --------------------------------------------------------------------
# Now verify against the hash of the original data.
# Get the corresponding public key.
set pubKey [new_CkPublicKey]
set success [CkPublicKey_LoadFromFile $pubKey "qa_data/ecc/secp256r1-pub.pem"]
if {$success == 0} then {
puts [CkPublicKey_lastErrorText $pubKey]
delete_CkPrivateKey $privKey
delete_CkBinData $bd
delete_CkCrypt2 $crypt
delete_CkEcc $ecdsa
delete_CkPrng $prng
delete_CkAsn $asn
delete_CkXml $xml
delete_CkPublicKey $pubKey
exit
}
# We already have the SHA256 hash of the original data (hashStr) so no need to re-do it..
set ecc2 [new_CkEcc]
set result [CkEcc_VerifyHashENC $ecc2 $hashStr $sig "base64" $pubKey]
if {$result != 1} then {
puts [CkEcc_lastErrorText $ecc2]
delete_CkPrivateKey $privKey
delete_CkBinData $bd
delete_CkCrypt2 $crypt
delete_CkEcc $ecdsa
delete_CkPrng $prng
delete_CkAsn $asn
delete_CkXml $xml
delete_CkPublicKey $pubKey
delete_CkEcc $ecc2
exit
}
puts "Verified!"
# Note: If we have only r,s and wish to reconstruct the ASN.1 signature, we do it like this:
set xml2 [new_CkXml]
CkXml_put_Tag $xml2 "sequence"
CkXml_NewChild2 $xml2 "int" $r
CkXml_NewChild2 $xml2 "int" $s
set asn2 [new_CkAsn]
CkAsn_LoadAsnXml $asn2 [CkXml_getXml $xml2]
set encodedSig [CkAsn_getEncodedDer $asn2 "base64"]
puts "encoded DSS signature: $encodedSig"
# You can go to https://lapo.it/asn1js/ and copy/paste the base64 encodedSig into the online tool, then press the "decode" button.
# You will see the ASN.1 such as this:
# SEQUENCE (2 elem)
# INTEGER (255 bit) 4849395540832462044300553275435608522154141569743642905628579547100940...
# INTEGER (255 bit) 3680701124244788134409868118208591399799457104230118295614152238560005...
delete_CkPrivateKey $privKey
delete_CkBinData $bd
delete_CkCrypt2 $crypt
delete_CkEcc $ecdsa
delete_CkPrng $prng
delete_CkAsn $asn
delete_CkXml $xml
delete_CkPublicKey $pubKey
delete_CkEcc $ecc2
delete_CkXml $xml2
delete_CkAsn $asn2