/* $Id: t_bdRsaCrack.c $ */ /* This code uses the free BIGDIGITS library version 2.3 available from http://di-mgt.com.au/bigdigits.html to show how the Chinese Remainder Theorem and Gauss's Method can be used to find a message encrypted by the RSA algorithm without having to factor the modulus. The same message must have been encrypted with public exponent e = 3 to three different recipients without any random padding. Ref: http://www.di-mgt.com.au/crt.html#crackingrsa Copyright (C) 2011 DI Management Services Pty Ltd. All rights reserved. */ /* Last updated: $Date: 2011-11-11 11:11:11 $ $Author: dai $ */ #include <stdio.h> #include "bigd.h" int debug = 0; int main(void) { BIGD m, e, n1, n2, n3, c1, c2, c3, N, N1, N2, N3, d1, d2, d3, s, t, x; m = bdNew(); e = bdNew(); n1 = bdNew(); n2 = bdNew(); n3 = bdNew(); c1 = bdNew(); c2 = bdNew(); c3 = bdNew(); N = bdNew(); N1 = bdNew(); N2 = bdNew(); N3 = bdNew(); d1 = bdNew(); d2 = bdNew(); d3 = bdNew(); s = bdNew(); t = bdNew(); x = bdNew(); /* Read in modulus values for three 512-bit public keys */ bdConvFromHex(n1, "A9C737DD808D02866FBF1ACF05DE2EB124137007A4965EC4DCBFA6D02F97E0123A8FD3691E414A1382F38AB39B09975705ECEAF1131A283C937B309F1C1417F9"); bdConvFromHex(n2, "B7E9E114A08ADFF12F762D7F0E1F16202E1EB7A7F2852369BDF44865783D19111E6D61B31DE987BCB9775099E220A798D4F99CD3E5F04C64F87A35C0268A83E9"); bdConvFromHex(n3, "C2BDBD4E36BA20D37D5D1E968F09F2FC7B41A97F3052274E4892D50D5FB337C923048AED7D393135EE55711E5C74975867F13D3845BAC9588B4BE170D08BAB57"); //bdSetShort(n1, 87); //bdSetShort(n2, 115); //bdSetShort(n3, 187); printf("Three public modulus values, 512 bits each...\n"); bdPrintHex("n1=", n1, "\n"); bdPrintHex("n2=", n2, "\n"); bdPrintHex("n3=", n3, "\n"); /* The three public keys all have public exponent e = 3 */ bdSetShort(e, 3); bdPrintHex("e=", e, "\n"); /* Set the common message m with no random padding (but large enough so m^3 > n_i) */ bdConvFromHex(m, "02ffffffffffffffffffffffffffffffffffffffffff0000deadbeefcafe"); //bdSetShort(m, 10); printf("Message to be encrypted...\n"); bdPrintHex("m=", m, "\n"); /* Create three ciphertexts, c_i = m^e mod n_i */ bdModExp(c1, m, e, n1); bdModExp(c2, m, e, n2); bdModExp(c3, m, e, n3); printf("Three ciphertexts...\n"); bdPrintHex("c1=", c1, "\n"); bdPrintHex("c2=", c2, "\n"); bdPrintHex("c3=", c3, "\n"); /* An eavedropper has the public values n1, n2, n3, c1, c2 and c3 */ /* Check that n1, n2, n3 are coprime in pairs */ bdGcd(t, n1, n2); bdPrintHex("gcd(n1,n2)=", t, "\n"); bdGcd(t, n2, n3); bdPrintHex("gcd(n2,n3)=", t, "\n"); bdGcd(t, n3, n1); bdPrintHex("gcd(n3,n1)=", t, "\n"); /* Compute N = n1 * n2 * n3 */ bdMultiply(t, n1, n2); bdMultiply(N, t, n3); if (debug) bdPrintDecimal("N=", N, "\n"); /* Compute N_i = N/n_i for i = 1,2,3 */ bdMultiply(N1, n2, n3); bdMultiply(N2, n1, n3); bdMultiply(N3, n1, n2); if (debug) bdPrintDecimal("N1=", N1, "\n"); if (debug) bdPrintDecimal("N2=", N2, "\n"); if (debug) bdPrintDecimal("N3=", N3, "\n"); /* Compute d_i = N_i^{-1} mod n_i for i = 1,2,3 */ bdModInv(d1, N1, n1); bdModInv(d2, N2, n2); bdModInv(d3, N3, n3); if (debug) bdPrintDecimal("d1=", d1, "\n"); if (debug) bdPrintDecimal("d2=", d2, "\n"); if (debug) bdPrintDecimal("d3=", d3, "\n"); /* Compute x = c_1 N_1 d_1 + c_2 N_2 d_2 + c_3 N_3 d_3 (mod N) */ bdModMult(s, c1, N1, N); bdModMult(x, s, d1, N); bdModMult(s, c2, N2, N); bdModMult(t, s, d2, N); bdAdd_s(x, x, t); bdModMult(s, c3, N3, N); bdModMult(t, s, d3, N); bdAdd_s(s, x, t); bdModulo(x, s, N); printf("Computed value of x = c_1 N_1 d_1 + c_2 N_2 d_2 + c_3 N_3 d_3 (mod N)...\n"); bdPrintHex("x=", x, "\n"); /* Compute the integer cube root of x */ bdCubeRoot(t, x); bdPrintHex("m'=cuberoot(x)=", t, "\n"); /* Do we have the correct answer? */ if (bdCompare(t, m) == 0) printf("HOORAY! We have found the correct answer, m' = m.\n"); else printf("OH BU**AR! We didn't find the correct answer.\n"); //clean_up: bdFree(&m); bdFree(&e); bdFree(&n1); bdFree(&n2); bdFree(&n3); bdFree(&c1); bdFree(&c2); bdFree(&c3); bdFree(&N); bdFree(&N1); bdFree(&N2); bdFree(&N3); bdFree(&d1); bdFree(&d2); bdFree(&d3); bdFree(&s); bdFree(&t); bdFree(&x); return 0; }