/* $Id: t_mpRSA508.c $ */ /***** BEGIN LICENSE BLOCK ***** * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * Copyright (c) 2001-15 David Ireland, D.I. Management Services Pty Limited * . All rights reserved. * ***** END LICENSE BLOCK *****/ /* * Last updated: * $Date: 2015-10-22 10:23:00 $ * $Revision: 2.5.0 $ * $Author: dai $ */ /* Test vector using BIGDIGITS to show RSA digital signature using 508-bit test vectors from "Some Examples of the PKCS Standards" An RSA Laboratories Technical Note Burton S. Kaliski Jr. Revised November 1, 1993 */ /* --- From the document:- In the example, the modulus n is the following 508-bit integer: n = 0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0 c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51 d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17 01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab The public exponent e is F4 (65537): e = 01 00 01 The private exponent d: d = 01 23 c5 b6 1b a3 6e db 1d 36 79 90 41 99 a8 9e a8 0c 09 b9 12 2e 14 00 c0 9a dc f7 78 46 76 d0 1d 23 35 6a 7d 44 d6 bd 8b d5 0e 94 bf c7 23 fa 87 d8 86 2b 75 17 76 91 c1 1d 75 76 92 df 88 81 RSA signing according to PKCS #1 has two general steps: An encryption block is constructed from a block type, a padding string, and the prefixed message digest; then the encryption block is exponentiated with Test User 1's private exponent. The encryption block EB is the following 64-octet string: 00 01 block type ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff padding string ff ff ff ff ff ff ff ff ff ff ff 00 00 separator 30 20 30 0c digestAlgorithm 06 08 2a 86 48 86 f7 0d 02 02 algorithm = md2 05 00 parameters = NULL 04 10 digest dc a9 ec f1 c1 5c 1b d2 66 af f9 c8 79 93 65 cd i.e. the 64-octet string: 00 01 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 00 30 20 30 0c 06 08 2a 86 48 86 f7 0d 02 02 05 00 04 10 dc a9 ec f1 c1 5c 1b d2 66 af f9 c8 79 93 65 cd The resulting encrypted message digest (the signature) is the following 64-octet string: 06 db 36 cb 18 d3 47 5b 9c 01 db 3c 78 95 28 08 02 79 bb ae ff 2b 7d 55 8e d6 61 59 87 c8 51 86 3f 8a 6c 2c ff bc 89 c3 f7 5a 18 d9 6b 12 7c 71 7d 54 d0 d8 04 8d a8 a0 54 46 26 d1 7a 2a 8f be CAUTION: Note that this example is for a digital signature, not encryption to keep a secret. To use RSA to encrypt a message, you should use *random* padding in the encryption block, different each time, not the fixed block of FF padding bytes used here, and you exponentiate with the recipient's *public* exponent. The recipient then deciphers using his private exponent. */ #include #include #include #include "bigdigits.h" #define MOD_SIZE 16 /* max 512-bits */ void pr_bytes(unsigned char *b, size_t nbytes) { size_t i; for (i = 0; i < nbytes; i++) { if (i && (i % 16 == 0)) printf("\n"); printf("%02x ", b[i]); } printf("\n"); } int main(void) { DIGIT_T n[MOD_SIZE], e[MOD_SIZE], d[MOD_SIZE]; DIGIT_T s[MOD_SIZE], m[MOD_SIZE], m1[MOD_SIZE], s1[MOD_SIZE]; size_t nbytes; char decimal[MOD_SIZE*4]; /* Data in big-endian byte format:- */ unsigned char nn[] = { 0x0A, 0x66, 0x79, 0x1D, 0xC6, 0x98, 0x81, 0x68, 0xDE, 0x7A, 0xB7, 0x74, 0x19, 0xBB, 0x7F, 0xB0, 0xC0, 0x01, 0xC6, 0x27, 0x10, 0x27, 0x00, 0x75, 0x14, 0x29, 0x42, 0xE1, 0x9A, 0x8D, 0x8C, 0x51, 0xD0, 0x53, 0xB3, 0xE3, 0x78, 0x2A, 0x1D, 0xE5, 0xDC, 0x5A, 0xF4, 0xEB, 0xE9, 0x94, 0x68, 0x17, 0x01, 0x14, 0xA1, 0xDF, 0xE6, 0x7C, 0xDC, 0x9A, 0x9A, 0xF5, 0x5D, 0x65, 0x56, 0x20, 0xBB, 0xAB, }; unsigned char ee[] = { 0x01, 0x00, 0x01 }; unsigned char dd[] = { 0x01, 0x23, 0xC5, 0xB6, 0x1B, 0xA3, 0x6E, 0xDB, 0x1D, 0x36, 0x79, 0x90, 0x41, 0x99, 0xA8, 0x9E, 0xA8, 0x0C, 0x09, 0xB9, 0x12, 0x2E, 0x14, 0x00, 0xC0, 0x9A, 0xDC, 0xF7, 0x78, 0x46, 0x76, 0xD0, 0x1D, 0x23, 0x35, 0x6A, 0x7D, 0x44, 0xD6, 0xBD, 0x8B, 0xD5, 0x0E, 0x94, 0xBF, 0xC7, 0x23, 0xFA, 0x87, 0xD8, 0x86, 0x2B, 0x75, 0x17, 0x76, 0x91, 0xC1, 0x1D, 0x75, 0x76, 0x92, 0xDF, 0x88, 0x81, }; unsigned char mm[] = { 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10, 0xDC, 0xA9, 0xEC, 0xF1, 0xC1, 0x5C, 0x1B, 0xD2, 0x66, 0xAF, 0xF9, 0xC8, 0x79, 0x93, 0x65, 0xCD, }; unsigned char ss[] = { 0x06, 0xDB, 0x36, 0xCB, 0x18, 0xD3, 0x47, 0x5B, 0x9C, 0x01, 0xDB, 0x3C, 0x78, 0x95, 0x28, 0x08, 0x02, 0x79, 0xBB, 0xAE, 0xFF, 0x2B, 0x7D, 0x55, 0x8E, 0xD6, 0x61, 0x59, 0x87, 0xC8, 0x51, 0x86, 0x3F, 0x8A, 0x6C, 0x2C, 0xFF, 0xBC, 0x89, 0xC3, 0xF7, 0x5A, 0x18, 0xD9, 0x6B, 0x12, 0x7C, 0x71, 0x7D, 0x54, 0xD0, 0xD8, 0x04, 0x8D, 0xA8, 0xA0, 0x54, 0x46, 0x26, 0xD1, 0x7A, 0x2A, 0x8F, 0xBE, }; printf("Test BIGDIGITS using 508-bit RSA key from 'Some Examples of the PKCS Standards'\n"); /* Convert bytes to BIGDIGITS */ mpConvFromOctets(n, MOD_SIZE, nn, sizeof(nn)); mpConvFromOctets(e, MOD_SIZE, ee, sizeof(ee)); mpConvFromOctets(d, MOD_SIZE, dd, sizeof(dd)); mpConvFromOctets(m, MOD_SIZE, mm, sizeof(mm)); mpConvFromOctets(s1, MOD_SIZE, ss, sizeof(ss)); mpPrintHex("n =", n, MOD_SIZE, "\n"); mpPrintHex("e =", e, MOD_SIZE, "\n"); mpPrintHex("d =", d, MOD_SIZE, "\n"); mpPrintHex("m =", m, MOD_SIZE, "\n"); /* Sign, i.e. Encrypt with private key, s = m^d mod n */ mpModExp(s, m, d, n, MOD_SIZE); mpPrintHex("s =", s, MOD_SIZE, " "); /* Did we get the same answer as expected? */ if (!mpEqual(s1, s, MOD_SIZE)) printf("<= ERROR - no match\n"); else printf("<= OK\n"); assert(mpEqual(s1, s, MOD_SIZE)); /* Verify, i.e. Decrypt with public key m' = s^e mod n */ mpModExp(m1, s, e, n, MOD_SIZE); mpPrintHex("m'=", m1, MOD_SIZE, " "); /* Check that we got back where we started */ if (!mpEqual(m1, m, MOD_SIZE)) printf("<= ERROR - no match\n"); else printf("<= OK\n"); assert(mpEqual(m1, m, MOD_SIZE)); /* Now convert back to octets (bytes) */ printf("Convert BIGDIGITS back to octets (bytes)...\n"); memset(mm, 0, sizeof(mm)); nbytes = mpConvToOctets(m, MOD_SIZE, mm, sizeof(mm)); printf("%d non-zero bytes converted from m:\n", nbytes); pr_bytes(mm, sizeof(mm)); memset(ee, 0, sizeof(ee)); nbytes = mpConvToOctets(e, MOD_SIZE, ee, sizeof(ee)); printf("%d non-zero bytes converted from e:\n", nbytes); pr_bytes(ee, sizeof(ee)); /* Do a conversion to decimal */ nbytes = mpConvToDecimal(e, MOD_SIZE, decimal, sizeof(decimal)); printf("%d non-zero decimal digits converted from e:\n", nbytes); printf("%s\n", decimal); assert(strcmp(decimal, "65537") == 0); printf("OK, successfully completed tests.\n"); return 0; }