Sample code for 30+ languages & platforms
PureBasic

DSA R,S Signature Values

See more DSA Examples

Creates a DSA signature. Gets r,s values from the signature. Re-creates the DSA signature ASN.1 from the r,s values. Then verifies the signature using the re-created ASN.1 DSA signature.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkXml.pb"
IncludeFile "CkDsa.pb"
IncludeFile "CkAsn.pb"
IncludeFile "CkCrypt2.pb"

Procedure ChilkatExample()

    success.i = 0

    ; This example requires the Chilkat API to have been previously unlocked.
    ; See Global Unlock Sample for sample code.

    crypt.i = CkCrypt2::ckCreate()
    If crypt.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkCrypt2::setCkEncodingMode(crypt, "hex")
    CkCrypt2::setCkHashAlgorithm(crypt, "sha-1")

    hashStr.s = CkCrypt2::ckHashFileENC(crypt,"qa_data/hamlet.xml")
    Debug "hash to sign: " + hashStr

    dsa.i = CkDsa::ckCreate()
    If dsa.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    pemPrivateKey.s
    pemPrivateKey = CkDsa::ckLoadText(dsa,"qa_data/dsa/dsaPrivKey2.pem")
    success = CkDsa::ckFromPem(dsa,pemPrivateKey)
    If success = 0
        Debug CkDsa::ckLastErrorText(dsa)
        CkCrypt2::ckDispose(crypt)
        CkDsa::ckDispose(dsa)
        ProcedureReturn
    EndIf

    ; Load the hash to be signed into the DSA object:
    success = CkDsa::ckSetEncodedHash(dsa,"hex",hashStr)
    If success = 0
        Debug CkDsa::ckLastErrorText(dsa)
        CkCrypt2::ckDispose(crypt)
        CkDsa::ckDispose(dsa)
        ProcedureReturn
    EndIf

    ; Sign the hash.
    success = CkDsa::ckSignHash(dsa)
    If success = 0
        Debug CkDsa::ckLastErrorText(dsa)
        CkCrypt2::ckDispose(crypt)
        CkDsa::ckDispose(dsa)
        ProcedureReturn
    EndIf

    ; Get the ASN.1 signature.
    asnSig.s = CkDsa::ckGetEncodedSignature(dsa,"base64")
    Debug "Signature: " + asnSig

    ; Examine the details of the ASN.1 signature.
    ; We want to get the r,s values as hex strings..
    asn.i = CkAsn::ckCreate()
    If asn.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkAsn::ckLoadEncoded(asn,asnSig,"base64")
    If success = 0
        Debug CkAsn::ckLastErrorText(asn)
        CkCrypt2::ckDispose(crypt)
        CkDsa::ckDispose(dsa)
        CkAsn::ckDispose(asn)
        ProcedureReturn
    EndIf

    ; Get the ASN.1 as XML.
    xml.i = CkXml::ckCreate()
    If xml.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkXml::ckLoadXml(xml,CkAsn::ckAsnToXml(asn))
    Debug "Signature as XML: "
    Debug CkXml::ckGetXml(xml)

    ; Sample XML shown here.
    ; The r and s values are the two hex strings in the XML.

    ; <?xml version="1.0" encoding="utf-8"?>
    ; <sequence>
    ;     <int>2C187F3AB6E47A66497B86CE97BB39E2133810F5</int>
    ;     <int>588E53D3F7B69636B48FD7175E99A3961BD7D775</int>
    ; </sequence>

    ; Pretend we're starting with r,s
    r.s = "2C187F3AB6E47A66497B86CE97BB39E2133810F5"
    s.s = "588E53D3F7B69636B48FD7175E99A3961BD7D775"

    ; Build the XML that will be converted to ASN.1
    CkXml::ckClear(xml)
    CkXml::setCkTag(xml, "sequence")
    CkXml::ckNewChild2(xml,"int",r)
    CkXml::ckNewChild2(xml,"int",s)

    ; Convert the XML to ASN.1
    success = CkAsn::ckLoadAsnXml(asn,CkXml::ckGetXml(xml))

    ; Emit the signature as DER encoded ASN.1 (base64)
    asnSig = CkAsn::ckGetEncodedDer(asn,"base64")

    ; --------------------------------------------------------------------
    ; Verify the signature using the asnSig we built from the r,s values
    ; --------------------------------------------------------------------

    dsa2.i = CkDsa::ckCreate()
    If dsa2.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    ; Load the DSA public key to be used for verification:
    pemPublicKey.s
    pemPublicKey = CkDsa::ckLoadText(dsa2,"qa_data/dsa/dsaPubKey2.pem")
    success = CkDsa::ckFromPublicPem(dsa2,pemPublicKey)
    If success = 0
        Debug CkDsa::ckLastErrorText(dsa2)
        CkCrypt2::ckDispose(crypt)
        CkDsa::ckDispose(dsa)
        CkAsn::ckDispose(asn)
        CkXml::ckDispose(xml)
        CkDsa::ckDispose(dsa2)
        ProcedureReturn
    EndIf

    ; Load the hash to be verified.
    success = CkDsa::ckSetEncodedHash(dsa2,"hex",hashStr)
    If success = 0
        Debug CkDsa::ckLastErrorText(dsa2)
        CkCrypt2::ckDispose(crypt)
        CkDsa::ckDispose(dsa)
        CkAsn::ckDispose(asn)
        CkXml::ckDispose(xml)
        CkDsa::ckDispose(dsa2)
        ProcedureReturn
    EndIf

    ; Load the ASN.1 signature:
    success = CkDsa::ckSetEncodedSignature(dsa2,"base64",asnSig)
    If success = 0
        Debug CkDsa::ckLastErrorText(dsa2)
        CkCrypt2::ckDispose(crypt)
        CkDsa::ckDispose(dsa)
        CkAsn::ckDispose(asn)
        CkXml::ckDispose(xml)
        CkDsa::ckDispose(dsa2)
        ProcedureReturn
    EndIf

    ; Verify:
    success = CkDsa::ckVerify(dsa2)
    If success = 0
        Debug CkDsa::ckLastErrorText(dsa2)
    Else
        Debug "DSA Signature Verified!"
    EndIf



    CkCrypt2::ckDispose(crypt)
    CkDsa::ckDispose(dsa)
    CkAsn::ckDispose(asn)
    CkXml::ckDispose(xml)
    CkDsa::ckDispose(dsa2)


    ProcedureReturn
EndProcedure