227 lines
7.3 KiB
C
227 lines
7.3 KiB
C
/* $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
|
|
* <http://www.di-mgt.com.au/bigdigits.html>. 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 <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#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;
|
|
}
|
|
|