/* MakeAliceRsaPss.c */ /* Create an X.509 certificate for Alice using RSA-PSS-SHA256 */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include "diCrPKI.h" #ifdef NDEBUG /* Make sure assertion testing is turned on */ #undef NDEBUG #endif #include <assert.h> /* Link with `diCrPKI.lib`. * In MSVC set * Configuration Properties > Linker > Input > Additional Dependencies=diCrPKI.lib; */ static void pr_x509dump(const char *certname); int main(void) { /* Required input files */ const char *issuercert = "CarlRSAPssSelf.cer"; // Carl the CA's certificate const char *issuerkey = "CarlRSAPSS.p8e"; // Carl's encrypted private key const char *subjectpubkey = "AliceRSAPSS.pub"; // Alice's public key /* Name of output certificate file to be created */ const char *certfile = "AliceRsaPssSignByCarl.cer"; char ski[PKI_SHA1_CHARS + 1]; /* Buffer for SHA-1 digest of public key*/ char extnbuf[512]; char *query; char qrybuf[128]; char *keystr; long r, nchars; /* Other fixed parameters */ const char *dn = "CN=AliceRSA;O=PSS;"; // Distinguished name /* Set a fixed serial number and validity dates */ const char *extns = "rfc822name=AliceRSA@example.com;" "serialNumber=#x47346BC7800056BC11D36E2EC410B3B0;" "notBefore=2018-04-01;" "notAfter=2039-12-31;" "subjectKeyIdentifier=" // Value to be added ; /* Set required key usage flags */ long ku = PKI_X509_KEYUSAGE_DIGITALSIGNATURE | PKI_X509_KEYUSAGE_NONREPUDIATION; /* Show we have the latest version of the core DLL */ printf("PKI_Version=%ld\n", PKI_Version(0, 0)); /* Compute SubjectKeyIdentifier from public key file (see RFC5280 s4.2.1.2) (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the value of the BIT STRING subjectPublicKey (excluding the tag, length, and number of unused bits). -- this is exactly the contents of the RSAPublicKey public key file created -- by this Toolkit. */ r = HASH_HexFromFile(ski, sizeof(ski) - 1, subjectpubkey, PKI_HASH_SHA1); printf("SKI=%s\n", ski); /* Compose Extensions parameter by appending the SKI value in hex */ strcpy_s(extnbuf, sizeof(extnbuf), extns); strcat_s(extnbuf, sizeof(extnbuf), ski); strcat_s(extnbuf, sizeof(extnbuf), ";"); printf("extns=[%s]\n", extnbuf); /* Create X.509 certificate file * using RSA-PSS-256 signature algorithm but setting the PSS parameter salt length to zero * so we get the same result each time. * Hint: this is for demonstration purposes. Use the default salt length in practice. */ r = X509_MakeCert(certfile, issuercert, subjectpubkey, issuerkey, 0, 0, dn, extnbuf, ku, "password", PKI_SIG_RSA_PSS_SHA256 | PKI_PSS_SALTLEN_ZERO | PKI_X509_AUTHKEYID); printf("X509_MakeCert(0 returns %ld (expecting 0)\n", r); assert(0 == r); /* Dump details about this new certificate */ pr_x509dump(certfile); /* Expected output: FILE: AliceRsaPssSignByCarl.cer X.509 CERTIFICATE Version: 3 Serial Number: #x47346BC7800056BC11D36E2EC410B3B0 Issuer: CN=CarlRSA;O=PSS Subject: CN=AliceRSA;O=PSS -----[cut]----- SHA-256 Thumbprint: 4a4783c4ed1be9052a3170f70ae1e24dde5da79a9df816e6b1f522203bccfbbf */ /* Query some information from it */ /* Expected output: X509_QueryCert(signatureAlgorithm)=rsaPSS X509_QueryCert(hashAlgorithm)=sha256 X509_QueryCert(pssParams)=sha256/mgf1SHA256/0/trailerFieldBC */ query = "signatureAlgorithm"; X509_QueryCert(qrybuf, sizeof(qrybuf) - 1, certfile, query, 0); printf("X509_QueryCert(%s)=%s\n", query, qrybuf); query = "hashAlgorithm"; X509_QueryCert(qrybuf, sizeof(qrybuf) - 1, certfile, query, 0); printf("X509_QueryCert(%s)=%s\n", query, qrybuf); query = "pssParams"; X509_QueryCert(qrybuf, sizeof(qrybuf) - 1, certfile, query, 0); printf("X509_QueryCert(%s)=%s\n", query, qrybuf); /* Show we can extract Alice's public key from it */ nchars = RSA_ReadAnyPublicKey(NULL, 0, certfile, 0); assert(nchars > 0); // Read into an internal key string keystr = malloc(nchars + 1); assert(keystr); nchars = RSA_ReadAnyPublicKey(keystr, nchars, certfile, 0); printf("Key length=%ld bits\n", RSA_KeyBits(keystr)); // Key length=2048 bits free(keystr); } /// Dump details of X.509 file to stdout static void pr_x509dump(const char *certname) { char *buf; long nchars; printf("FILE: %s\n", certname); // New function in v12 nchars = X509_TextDumpToString(NULL, 0, certname, 0); if (nchars <= 0) { printf("**ERROR %ld\n", nchars); return; } buf = malloc(nchars + 1); assert(buf); nchars = X509_TextDumpToString(buf, nchars, certname, 0); printf("%s\n", buf); free(buf); }