Sample code for 30+ languages & platforms
Xbase++

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 Xbase++ Downloads

Xbase++
LOCAL nSuccess
LOCAL oPrivKey
LOCAL oBd
LOCAL oCrypt
LOCAL cHashStr
LOCAL oEcdsa
LOCAL oPrng
LOCAL cSig
LOCAL oAsn
LOCAL oXml
LOCAL r
LOCAL s
LOCAL oPubKey
LOCAL oEcc2
LOCAL nResult
LOCAL oXml2
LOCAL oAsn2
LOCAL cEncodedSig

nSuccess := 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.
oPrivKey := CreateObject("Chilkat.PrivateKey")
nSuccess := oPrivKey:LoadEncryptedPemFile("qa_data/ecc/secp256r1-key-pkcs8-secret.pem", "secret")
IF (nSuccess == 0)
    ? oPrivKey:LastErrorText
    oPrivKey:destroy()
    RETURN
ENDIF

//  Sign the SHA256 hash of some data.
oBd := CreateObject("Chilkat.BinData")
nSuccess := oBd:LoadFile("qa_data/hamlet.xml")
IF (nSuccess == 0)
    ? "Failed to load file to be hashed."
    oPrivKey:destroy()
    oBd:destroy()
    RETURN
ENDIF

oCrypt := CreateObject("Chilkat.Crypt2")
oCrypt:HashAlgorithm := "sha256"
oCrypt:EncodingMode := "base64"
cHashStr := oCrypt:HashBdENC(oBd)

oEcdsa := CreateObject("Chilkat.Ecc")
oPrng := CreateObject("Chilkat.Prng")
//  Returns ASN.1 signature as a base64 string.
cSig := oEcdsa:SignHashENC(cHashStr, "base64", oPrivKey, oPrng)
? "sig = " + cSig

//  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:
oAsn := CreateObject("Chilkat.Asn")
oAsn:LoadEncoded(cSig, "base64")
oXml := CreateObject("Chilkat.Xml")
oXml:LoadXml(oAsn:AsnToXml())

? oXml:GetXml()

//  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
r := oXml:GetChildContentByIndex(0)
s := oXml:GetChildContentByIndex(1)

? "r = " + r
? "s = " + s

//  --------------------------------------------------------------------
//  Now verify against the hash of the original data.

//  Get the corresponding public key.
oPubKey := CreateObject("Chilkat.PublicKey")
nSuccess := oPubKey:LoadFromFile("qa_data/ecc/secp256r1-pub.pem")
IF (nSuccess == 0)
    ? oPubKey:LastErrorText
    oPrivKey:destroy()
    oBd:destroy()
    oCrypt:destroy()
    oEcdsa:destroy()
    oPrng:destroy()
    oAsn:destroy()
    oXml:destroy()
    oPubKey:destroy()
    RETURN
ENDIF

//  We already have the SHA256 hash of the original data (hashStr) so no need to re-do it..
oEcc2 := CreateObject("Chilkat.Ecc")
nResult := oEcc2:VerifyHashENC(cHashStr, cSig, "base64", oPubKey)
IF (nResult != 1)
    ? oEcc2:LastErrorText
    oPrivKey:destroy()
    oBd:destroy()
    oCrypt:destroy()
    oEcdsa:destroy()
    oPrng:destroy()
    oAsn:destroy()
    oXml:destroy()
    oPubKey:destroy()
    oEcc2:destroy()
    RETURN
ENDIF

? "Verified!"

//  Note: If we have only r,s and wish to reconstruct the ASN.1 signature, we do it like this:
oXml2 := CreateObject("Chilkat.Xml")
oXml2:Tag := "sequence"
oXml2:NewChild2("int", r)
oXml2:NewChild2("int", s)

oAsn2 := CreateObject("Chilkat.Asn")
oAsn2:LoadAsnXml(oXml2:GetXml())
cEncodedSig := oAsn2:GetEncodedDer("base64")
? "encoded DSS signature: " + cEncodedSig

//  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...

oPrivKey:destroy()
oBd:destroy()
oCrypt:destroy()
oEcdsa:destroy()
oPrng:destroy()
oAsn:destroy()
oXml:destroy()
oPubKey:destroy()
oEcc2:destroy()
oXml2:destroy()
oAsn2:destroy()