I am working on developing an application for a smart card reader, using the Visa test kit in the C language. On reading card number 2, am getting the following Issuer Public Key Certificate after reading the card:
uint8_t ISSUER_PK_CERTIFICATE[] = {41 03 b1 61 f7 dd 14 34 85 79 1b f6 01 04 ea 10 08 06 9d 16 b6 c3 b3 5b 4e 37 ed 20 25 66 d8 77 6f 48 02 28 32 0a 90 31 ae 28 28 75 fa 1b 3a bf c7 6d 15 6f f4 b5 08 4a fd 9c b0 ef b0 8a 8e 5b 41 fa be 99 3b 04 fe 1b 76 8d ef b6 eb ae d1 77 4d d0 5e 7f f7 0c 45 86 42 85 e6 d0 06 2d 86 65 4e 7a 88 5f 49 f9 f3 11 9f 24 35 18 4c 28 1c 14 93 d2 ac 69 ec c7 88 da c0 75 9a 73 ec d5 f0 28 b3 27 a1 e5 1d c5 cb 43 53 7b 1d 2a a7 04 62 cd a3 c8 74 a5 7c 45 8e 52 15 09 ff 98 73 71 d6 da 8d 7a 4f f5 6f 10 87 89 68 86 33 17 1e f1 d6 9d},
...(ignoring the specifics of formatting in C arrays) where the modulus is 176 and from Visa, I have the following CA Public Key Modulus. The cards are test cards, thus I have no problem sharing the output publicly:
uint8_t VISA_PK_MODULUS[] = {99 6A F5 6F 56 91 87 D0 92 93 C1 48 10 45 0E D8 EE 33 57 39 7B 18 A2 45 8E FA A9 2D A3 B6 DF 65 14 EC 06 01 95 31 8F D4 3B E9 B8 F0 CC 66 9E 3F 84 40 57 CB DD F8 BD A1 91 BB 64 47 3B C8 DC 9A 73 0D B8 F6 B4 ED E3 92 41 86 FF D9 B8 C7 73 57 89 C2 3A 36 BA 0B 8A F6 53 72 EB 57 EA 5D 89 E7 D1 4E 9C 7B 6B 55 74 60 F1 08 85 DA 16 AC 92 3F 15 AF 37 58 F0 F0 3E BD 3C 5C 2C 94 9C BA 30 6D B4 4E 6A 2C 07 6C 5F 67 E2 81 D7 EF 56 78 5D C4 D7 59 45 E4 91 F0 19 18 80 0A 9E 2D C6 6F 60 08 05 66 CE 0D AF 8D 17 EA D4 6A D8 E3 0A 24 7C 9F},
also ignoring the formatting (I have written it like that here for simplicity), where the modulus is also 176. The CA Public Key index is 5 and the exponent is 3, that's how I retrieved the above key. Now, I have written the following function to implement the RSA decryption algorithm to be able to verify the signature of the certificate:
uint32_t buffer[ISSUER_PK_CERTIFICATE_LENGTH]; //this holds the "decrypted" data
void decryptCertificate(uint8_t exponent)
{
uint32_t buffer[ISSUER_PK_CERTIFICATE_LENGTH]; //the length is in hex
for(int i = 0; i < hexToDecimal(ISSUER_PK_CERTIFICATE_LENGTH); i++) //conversion to integer for my convenience
{
uint32_t powered = pow(ISSUER_PK_CERTIFICATE[i], exponent);
uint32_t remainder = powered / VISA_PK_MODULUS[i];
uint32_t multiplied = remainder * VISA_PK_MODULUS[i];
uint32_t original = powered - multiplied;
buffer[i] = original;
}
}
but the final "decrypted" array does not fit the requirements of the Validation test specified by VISA. Anyone see where I could have gone wrong in the implementation of the above algorithm or can someone point me in the right direction if I have gone wrong? the output of the decryption is as shown:
8f 1b 94 1f 2d 3d 23 00 8b 40 be 00 01 40 06 d0 24 0c 2e 2e 5c 03 35 16 82 7d 5c 08 7b 94 67 4b 0b 84 02 00 8a 14 01 c9 20 9e 98 5d 1c 63 8c 08 43 35 27 14 0c 3d 86 94 61 81 4c 27 3a 48 d0 31 05 01 20 3f b3 40 a1 77 1b 4b ef 5b ab 60 36 38 31 1c 18 01 3d 01 45 e0 43 13 6e 43 d8 4e 6e 29 7a 08 70 41 48 27 37 11 28 00 32 5a 0a 10 34 3e 00 00 0d 49 b0 c7 36 08 30 4d 00 1b 08 99 00 11 b3 27 3d 19 01 35 0c 03 07 2a 5e ed 2f 40 20 8d 02 39 2f 45 13 bd 0d 10 2d 09 41 08 25 08 58 00 01 2c 51 05 06 07 13 a1 cc 0a 1b 88 00 01 04 97
NB: The Visa Specification states the Recovery function as: X = Recover(PK)[S] = Se mod n, given a digital Signature S and public key PK
It appears that you're trying to perform RSA decryption on each byte individually. This is incorrect — the certificate and modulus arrays each represent a single big integer. You will need to use a big-integer math library (or a special-purpose crypto library) to perform this decryption.