These days public keys are typically presented as ASN.1 encoded X.509 certificates (see RFC 3280) or, with additional information, in password protected PKCS #12 files or "protocol data units" (PDUs) (see RFC 2437). PKCS #8 PDUs are also used for the storage and transport of private keys.
The first step in using such key formats with CDK functions is to load the certificate or PKCS #8/12 PDU into an object of the appropriate CDK class (cdk::Cert or cdk::Key). Once the PDU is parsed, its components can be accessed separately or used in a wide variety of public and private key operations. The code fragments below illustrate several of the most popular operations.
x, use a statement of the form:if(x[0]!=0x30) x = x.tobin64() (x[0]!=0x30) is true when the PDU begins with the character 'M' as it does when it is base64-encoded, whereas all binary ASN.1 encoded PDUs under consideration here start with the tag '\x30' for an ASN.1 BER- or DER-encoded SEQUENCE.)
cdk::str strCertificate = // a sample base64-encoded certificate "MIICJzCCAZCgAwIBAgIBGDANBgkqhkiG9w0BAQUFADBAMQswCQYDVQQGEwJVUzEM" "MAoGA1UEChMDSVNDMSMwIQYDVQQDExpJU0MgQ0RLIFNhbXBsZSBDZXJ0aWZpY2F0" "ZTAeFw0wMzA3MTcwMDAwMDBaFw0wNDA3MTcwMDAwMDBaMEAxCzAJBgNVBAYTAlVT" "MQwwCgYDVQQKEwNJU0MxIzAhBgNVBAMTGklTQyBDREsgU2FtcGxlIENlcnRpZmlj" "YXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9GQTkukn+153rATR8dh2H" "m8ixF7f7Y7bI0VFJnJAQCKqta4/IhFwQIK5F2Gn8j9tITBiXCF7F6XSvaF8bivN1" "0zR0pvI11NflEm2kwh7Yw0jZJB17Y3FHg183qYegmm/UwqX5zKUa4xw+cE8XSEqU" "uwjg0roBMGhAMzFEihHzLwIDAQABozEwLzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB" "/wQEAwIAYDAPBgNVHQ4ECHJzYS0xMDI0MA0GCSqGSIb3DQEBBQUAA4GBALWGxxo5" "5ScpLfECnqEUixFwrzftQGD2ISda7EWp/d7k23fOXgHC7Za18OpvlBUZ3sC2Fg4f" "infRHd2J4mXONk5OEdjhJILd58GErcCECg4J2uJPz77/zk+giiXldQEPtG+YOaAb" "ZC2SFbdfyYDKiSPhgzdy0/b4cElf4+VzegRM"; // decode the certificate if it is base64-encoded (this one is!) if (strCertificate[0] != 0x30) strCertificate = strCertificate.tobin64(); // load binary ASN.1 encoded certificate data into a Cert object cdk::Cert c1; c1.load(strCertificate); // nonzero return value indicates parsing error // now individual certificate components may be accessed cdk::str strPub, strAlgID; // output buffers for: strPub = c1.subject_pub; // subjectPublicKey and strAlgID = c1.subject_oid; // subject AlgorithmIdentifier
cdk::str strP12 = // a sample base64-encoded PKCS #12 PDU "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" "hpvt5t+Kn4IECCYQiCMLyK+cAgIEAA=="; // decode the PDU if it is base64-encoded (this one is!) if (strP12[0] != 0x30) strP12 = strP12.tobin64(); // parse the PDU cdk::Chain chn; // buffer for PDU's certificate chain cdk::str p12oid, strPrv; // buffers for algID and private key cdk::str crl; // buffer for any CRLs cdk::parsep12(strP12, "password", chn, p12oid, strPrv, crl); // a nonzero return value indicates a parsing error // find end-user's certificate in the chain int nEndUserCert = chn.find(Chain::user); if (nEndUserCert == -1) nEndUserCert = 0; // leaf certificate not found // and load it into a new Cert object cdk::Cert c1; c1.load(chn.index(nEndUserCert)); // now we can access individual certificate components cdk::str strPub, strAlgID; // output buffers for: strPub = c1.subject_pub; // subjectPublicKey and strAlgID = c1.subject_oid; // subject AlgorithmIdentifier
For encryption and signature validation, only the public key is required:
// load an ASN.1 encoded public key into a new Key object cdk::Key key; key.loadoid(strAlgID); // a nonzero return value indicates an error key.loadpub(strPub); // a nonzero return value indicates an error
For decryption and signing, you'll need the entire key pair:
// load an ASN.1 encoded key pair into a new Key object cdk::Key key; key.loadoid(strAlgID); // a nonzero return value indicates an error key.loadprv(strPrv); // a nonzero return value indicates an error key.loadpub(strPub); // a nonzero return value indicates an error
// load an ASN.1 encoded private key and recompute the public key cdk::Key key; key.loadoid(strAlgID); // a nonzero return value indicates an error key.loadprv(strPrv); // a nonzero return value indicates an error key.genpub(); // a nonzero return value indicates an error
To obtain ASN.1 encoded key information from an existing Key object:
cdk::Key key; // assume this contains a complete key pair cdk::str strAlgID, strPub, strPrv; // output buffers for requested components strAlgID = key.asn1parameters(1,0); // get the key's algorithm identifier strPub = key.asn1public(); // get the public key strPrv = key.asn1private(); // get the (unprotected) private key
To load raw RSA public key components into a Key object:
cdk::str strRSAPUB = hex( // a sample public modulus "D025F3A723231FA23CE4CE011A595787A06707AEA61443E15FAEDD6D59634E44" "BA5CE36695C4D441160F3A2FB9CC757542F60804E94A58B610722EBFDE3DBF08" "3F6FDD88AE6F282BF215542C929AF95F0A8FD44CC669A6CB72C9B920305E3B4D" "13AEADE6A53CAC1BD9E9BC4037A6D4F18E6B94430DBEABF1697121418A2A6AC7" ); // load the binary modulus with the popular public exponent 65537 (F4) cdk::Key key; key.RSALoadPublic(num(65537), num(strRSAPUB)); // a nonzero return value indicates an error
To load raw RSA key pair components into a Key object, load the private components followed by the public ones, then call setup() to compute the intermediate internal private key components (such as Chinese Remainder Theorem coefficients):
cdk::str strRSAP = hex( // a prime "D0A1379B3EBFA301DC59196F18593C45E519287A23297589109F4B3C50D7B0DF" "729D299BC6F8E9EF9066971FB444AC06613FC8D63795BE9AD0BEAF5501193B31" ); cdk::str strRSAQ = hex( // another prime "FF68BF231FF2B3704AEDE04EECB51E50CA698EFD50A1379B3EBFA301DC59196F" "18593C45E519287A23297589109F4B3C50D7B0DF729D299BC6F8E9EF90669777" ); cdk::str strRSAPUB = hex( // the product "D025F3A723231FA23CE4CE011A595787A06707AEA61443E15FAEDD6D59634E44" "BA5CE36695C4D441160F3A2FB9CC757542F60804E94A58B610722EBFDE3DBF08" "3F6FDD88AE6F282BF215542C929AF95F0A8FD44CC669A6CB72C9B920305E3B4D" "13AEADE6A53CAC1BD9E9BC4037A6D4F18E6B94430DBEABF1697121418A2A6AC7" ); // load the prime factors of the modulus as the private key cdk::Key key; key.rsai.loadpriv(num(strRSAP), num(strRSAQ)); // a nonzero return value indicates an error // load the modulus with the exponent 65537 (F4) as the public key key.RSALoadPublic(num(65537), num(strRSAPUB)); // a nonzero return value indicates an error key.rsai.setup(); // computes internal RSA private key values
To load raw RSA private key components and reconstruct the corresponding public key components:
cdk::str strRSAP = hex( // a prime "D0A1379B3EBFA301DC59196F18593C45E519287A23297589109F4B3C50D7B0DF" "729D299BC6F8E9EF9066971FB444AC06613FC8D63795BE9AD0BEAF5501193B31" ); cdk::str strRSAQ = hex( // another prime "FF68BF231FF2B3704AEDE04EECB51E50CA698EFD50A1379B3EBFA301DC59196F" "18593C45E519287A23297589109F4B3C50D7B0DF729D299BC6F8E9EF90669777" ); // load the prime factors of the modulus as the private key cdk::Key key; key.rsai.loadpriv(num(strRSAP), num(strRSAQ)); // a nonzero return value indicates an error // specify a public exponent and recompute internal RSA private key values key.rsai.expo = num(65537); // 65537 is a popular choice key.rsai.setup(); // a nonzero return value indicates an error // now regenerate the public components key.rsai.genpub(); // a nonzero return value indicates an error
To obtain raw key components from a Key object containing a complete RSA key pair:
cdk::Key key; // assume that this contains a complete key pair num p, q, pq, expo // ouput buffers for key components key.RSAGetRawPublic(expo, pq); // access the public exponent and modulus p = key.rsai.p; // access the first prime factor q = key.rsai.q; // access the second prime factor
The code fragments in this section illustrate how to generate a new DSA parameter set (using the CDK's DSA_GenerateParameters() function) and then ASN.1 encode it. If you already have a set of raw DSA parameters, you can follow this example to obtain an ASN.1 encoded representation -- just skip the parameter generation step:
// generate a new 1024-bit DSA parameter set int nNP = 1024; // requested size of p in bits; denoted by L in FIPS 186-2 int H = 2; // base for g (default value is NIST's 2; ISC uses 7) cdk::num p, q, g; // output buffers for DSA parameters int start = 0; // starting value of counter int counter = 0; // output buffer for final iteration count cdk::str seed = cdk::getrand2(20); // initial random 20-byte seed value PRNG pi; // SHA-1 based PRNG to use if we need more seed values // retry until we find a suitable seed while ( DSA_GenerateParameters(seed,160,nNP,q,p,g,counter,start,H) == CDK_INVALID_SEED ) strSeed = pi.gens(20); // obtain hexadecimal representations of p,q,g cdk::str strQ = q.tostr().tohex(1); cdk::str strP = p.tostr().tohex(1); cdk::str strG = g.tostr().tohex(1); // populate a GroupData object with these parameters cdk::GroupData cd; cd.deg = 1; // flag for SHA-1 (for ECDSA, degree of field extension) cd.seed = ""; // seed is not encoded with parameters cd.order = strQ.c_str(); // q cd.p = strP.c_str(); // p cd.a = 0; // only for ECDSA (1st polynomial coefficient) cd.b = 0; // only for ECDSA (2nd polynomial coefficient) cd.Gx = strG.c_str(); // g (for ECDSA, x coordinate of EC base point) cd.Gy = 0; // only for ECDSA (y coordinate of base point) cd.start = 0; cd.genseed = H; // get an ASN.1 encoded algorithm ID for these parameters cdk::str strAlgID = cd.oid();
If you want to use one of the predefined DSA parameter sets provided by ISC in parms.c, you can quickly get its algorithm ID without explicitly constructing a GroupData object. For example, the ASN.1 encoded algorithm ID for ISC's 1024-bit DSA parameters can be obtained as follows:
cdk::str strAlgID = DSA_Parms[ISCDSA1024].oid();
Once you have the ASN.1 encoded algorithm ID for a DSA key, you can load its raw public key component like this:
cdk::str strDLPUB = hex( // a sample public key "19131871D75B1612A819F29D78D1B0D7346F7AA77BB62A859BFD6C5675DA9D21" "2D3A36EF1672EF660B8C7C255CC0EC74858FBA33F44C06699630A76B030EE333" ); cdk::Key key; key.loadoid(DSA_Parms[FIPSEXAMPLE].oid()); // load algorithm ID key.DLLoadPublic(num(strDLPUB)); // load public key value
To load raw DSA public and private key components:
cdk::str strDLPRV = hex("2070b3223dba372fde1c0ffc7b2e3b498b260614"); cdk::str strDLPUB = hex( "19131871D75B1612A819F29D78D1B0D7346F7AA77BB62A859BFD6C5675DA9D21" "2D3A36EF1672EF660B8C7C255CC0EC74858FBA33F44C06699630A76B030EE333" ); cdk::Key key; key.loadoid(DSA_Parms[FIPSEXAMPLE].oid()); // load algorithm ID key.loadprivate(num(strDLPRV)); // load private key value key.DLLoadPublic(num(strDLPUB)); // load public key value
To load raw DSA private key components and generate the corresponding public key:
cdk::str strDLPRV = hex("2070b3223dba372fde1c0ffc7b2e3b498b260614"); cdk::str strDLPUB = hex( "19131871D75B1612A819F29D78D1B0D7346F7AA77BB62A859BFD6C5675DA9D21" "2D3A36EF1672EF660B8C7C255CC0EC74858FBA33F44C06699630A76B030EE333" ); cdk::Key key; key.loadoid(DSA_Parms[FIPSEXAMPLE].oid()); // load algorithm ID key.loadprivate(num(strDLPRV)); // load private key value key.genpub();
To extract raw key components from a Key object containing a complete DSA or ECDSA key pair:
cdk::Key key; // assume this contains a (EC)DSA key pair num priv, pub, y; // output buffers for raw components // get an ASN.1 encoded algorithm ID containing the (EC)DSA parameters cdk::str strAlgID = key.asn1parameters(1,0); key.GetRawPrivate(priv); // get raw private key key.DLGetRawPublic(pub, y); // y is only used for ECDSA; ignore for DSA
The following code fragment shows how to create an algorithm identifier specifying the elliptic curve labeled 'P-192' by NIST:
// create an ASN.1 encoded algorithm ID for NIST Curve P-192 cdk::GroupData cd; cd.deg = 0; cd.a = "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC"; cd.seed = "0x3045AE6FC8422F64ED579528D38120EAE12196D5"; cd.order = "0xFFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"; cd.p = "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"; cd.b = "0x64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1"; cd.Gx = "0x188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"; cd.Gy = "0x7192B95FFC8DA78631011ED6B24CDD573F977A11E794811"; cd.start = 0; cd.genseed = 0; cdk::str strECDSAP192 = cd.oid();
The following code fragment shows how to create an algorithm identifier specifying the Koblitz curve labeled 'K-163' by NIST:
// create an ASN.1 encoded algorithm ID for NIST Curve K-163 cdk::GroupData cd; cd.deg = 163; cd.a = "0x1"; cd.seed = ""; cd.order = "0x04000000000000000000020108a2e0cc0d99f8a5ef"; cd.p = "0x0800000000000000000000000000000000000000c9"; cd.b = "0x1"; cd.Gx = "0x02fe13c0537bbc11acaa07d793de4e6d5e5c94eee8"; cd.Gy = "0x0289070fb05d38ff58321f2e800536d538ccdaa3d9"; cd.start = 0; cd.genseed = 0; cdk::str strECDSAK163 = cd.oid();
Of course, since the CDK provides predefined parameter sets for these two curves, it isn't necessary to explicitly construct the algorithm IDs yourself! You can simply use the oid() method after picking out the appropriate element of the NIST_Curves[] array. Here are two examples:
strECDSAP192 = NIST_Curves[NISTP192].oid(); strECDSAK163 = NIST_Curves[NISTK163].oid();
Once you have an ASN.1 encoded algorithm identifier for your key type you can load raw ECDSA private key components into a Key object and then generate the corresponding public key components as follows:
cdk::str strECPRV = cdk::hex("AA8A7935B06BC5CA9749BBA4053A999667C0FDA287B759E1"); cdk::Key k9; k9.loadoid(NIST_Curves[0].oid()); // a nonzero return value indicates an error k9.loadprivate(num(strECPRV)); k9.genpub(); // a nonzero return value indicates an error
// generate a 1024-bit RSA key with 2 primes and a public exponent of 65537 cdk::Key key; key.RSAkeygen(cdk::getrand2(80)); // a nonzero return value indicates an error
cdk::Key key; key.DLkeygen(cdk::getrand2(80), DSA_Parms[ISCDSA1024].oid()); // a nonzero return value indicates an error
cdk::Key key; key.DLkeygen(cdk::getrand2(80), NIST_Curves[NISTP384].oid()); // a nonzero return value indicates an error
cdk::Key key; // contains signer's private key cdk::Signature sig; // output buffer for signature // sample SHA-1 digest to be signed cdk::str digest = hex("A9993E364706816ABA3E25717850C26C9CD0D89D"); num seed = 0; // we may need a random seed value // a random seed is only required for DSA and ECDSA, not RSA if (!key.isRSA()) num seed = num(cdk::getrand2(80)); key.Sign(num(digest), seed, sig);
To obtain an ASN.1 encoded digital signature from a cdk::Signature object, you may use the toasn1() function:
cdk::Signature sig; // contains signature to be extracted // get an ASN1. encoded represention of the signature cdk::str strSignature = sig.toasn1();
There are two ways to extract a digital signature in "raw" form. The first option is to use the toraw() method like this:
cdk::Signature sig; // contains signature to be extracted // get a raw (binary) represention of the signature cdk::str strSignature = sig.toraw();
The second method is to explicitly extract the signature components as shown here:
cdk::Key key; // contains signer's private key cdk::Signature sig; // contains signature to be extracted // get the raw signature component(s) num r,s; if (!key.isRSA()) r = sig.r; // we only need r for DSA and ECDSA s = sig.s; // we can convert r and s to hex-encoded strings as follows: cdk::str strR, strS; if (!k1.isRSA()) strR = r.tostring().tohex(); strS = s.tostring().tohex();
cdk::Key key; // contains purported signer's public key cdk::str digest; // contains message digest input cdk::str strASN1Signature; // contains the ASN.1 encoded signature // load the ASN.1 signature into a new Signature object cdk::Signature sig; sig.load(strASN1Signature); // nonzero return value indicates error // and attempt to validate it int i = key.SignCheck(num(digest), sig); // returns zero if valid printf("Signature is %s", i ? "INVALID!" : "valid");
To verify a signature represented as raw signature components (possibly obtained using the toraw() method described above), use the following:
cdk::Key key; // contains purported signer's public key cdk::Signature sig; // contains signature to be verified cdk::str digest; // contains message digest // explicitly load the relevant signature components if (!key.isRSA()) // we only need r for DSA and ECDSA sig.r = r; sig.s = s; int i = key.SignCheck(num(digest), sig); // returns zero if valid printf("Signature is %s", i ? "INVALID!" : "valid");
cdk::Key pubKey; // this contains recipient's public key cdk::str sessionKey; // this contains the random session key // wrap the session key cdk::str wrappedKey; // output buffer for the wrapped key pubKey.Encrypt(sessionKey, wrappedKey);// nonzero return value indicates error
sessionKey can be used with AES or TDES to encrypt the data, then the ciphertext and wrappedKey are transmitted to the recipient.
cdk::Key prvKey; // this contains recipient's private key cdk::str wrappedKey; // wrapped key received from sender // unwrap the session key cdk::str sessionKey; // output buffer for session key prvKey.Decrypt(wrappedKey, sessionKey);// nonzero return value indicates error
The recipient now loads the unwrapped sessionKey into the appropriate cipher object (AES, DES, etc.) and decrypts the data.
The code fragment below illustrates how to implement the DH protocol using a single CDK function. It applies equally well to DSA keys and ECDSA keys, but cannot be used with RSA keys.
// assume that Ann has her own key pair in k1 and Bob's public key in k2 cdk::Key k1, k2; // she computes: cdk::Point secretA = k2.pub * k1.getPrivate(); // assume that Bob has his own key pair in k3 and Ann's public key in k4 cdk::Key k3, k4; // he computes: cdk::Point secretB = k4.pub * k3.getPrivate(); // now, secretA = secretB, so Ann and Bob share a secret no eavesdropper // with only their public keys could compute
For information concerning the objects/methods used here see:
The next topic is Handling PKCS PDUs (including CMS).
| ISC Cryptographic Development Kit - User's Guide | |
| Questions? E-mail ISC technical support | |
| Copyright© 2002-2006 Information Security Corp. All rights reserved. |