This library implements some hash and cryptographic algorithms.

Dependents:   mBuinoBlinky PB_Emma_Ethernet SLOTrashHTTP Garagem ... more

This library implements the following algorithms :

  • RC4
  • AES (AES-128, AES-192, AES-256)
  • DES
  • Triple DES (EDE)
  • MD2
  • MD4
  • MD5
  • SHA-1
  • SHA-2 (SHA-224, SHA-256, SHA-384, SHA-512)

The hash algorithms have been optimized for the mbed and you should get decent performance. However, I did not optimize the ciphers. Also, I did not test extensively these algorithms : it should work but you may find some bugs. Block ciphers support two modes : ECB and CBC.

Warning

If you are using SHA-384 or SHA-512, be aware that it produces large binary files and the compilation (using the online compiler) takes much longer to execute. It may happen that the compiler stops because it timed-out. In this case, just compile again and it should work.

Computing hash

You can compute the hash of some data in two different ways. The first one is the easiest, each hash algorithm has a static method that takes some data and compute the hash from it.

Computing hash using method 1

#include "Crypto.h"
#include "mbed.h"

static const char msg[] = "mbed is great !";

int main()
{
    uint8_t hash[16];
    MD2::computeHash(hash, (uint8_t*)msg, strlen(msg));
    printf("hash: ");
    for(int i = 0; i < 16; ++i)
        printf("%02x", hash[i]);
    printf("\n");
    
    return 0;
}

The second one is slightly slower (around 2-3% slower) but it allows you to compute the hash of some data in several steps (by calling update method). This is the method you should use if you need to compute the hash from a large source and you don't have enough memory to store it in a single buffer.

Computing hash using method 2

#include "Crypto.h"
#include "mbed.h"

static const char msg[] = "mbed is great !";

int main()
{
    uint8_t hash[16];
    MD2 h;
    h.update((uint8_t*)msg, strlen(msg));
    h.finalize(hash);
    printf("hash: ");
    for(int i = 0; i < 16; ++i)
        printf("%02x", hash[i]);
    printf("\n");
    
    return 0;
}

TODO

  • optimize ciphers
  • add doc
Committer:
feb11
Date:
Thu Sep 12 16:03:43 2013 +0000
Revision:
6:19aa835f2bbb
Parent:
5:06cd9c8afa0b
change public API for hash + small improvements for hash + rearrange code

Who changed what in which revision?

UserRevisionLine numberNew contents of line
feb11 4:0da19393bd57 1 /**
feb11 4:0da19393bd57 2 Implementation of MD2 as described here:
feb11 4:0da19393bd57 3 http://tools.ietf.org/html/rfc1319
feb11 4:0da19393bd57 4 */
feb11 4:0da19393bd57 5
feb11 0:7a1237bd2d13 6 #include "MD2.h"
feb11 0:7a1237bd2d13 7 #include <string.h>
feb11 0:7a1237bd2d13 8
feb11 0:7a1237bd2d13 9 static const uint8_t s[] =
feb11 0:7a1237bd2d13 10 {
feb11 0:7a1237bd2d13 11 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36, 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13,
feb11 0:7a1237bd2d13 12 0x62, 0xA7, 0x05, 0xF3, 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C, 0x82, 0xCA,
feb11 0:7a1237bd2d13 13 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16, 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12,
feb11 0:7a1237bd2d13 14 0xBE, 0x4E, 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E, 0xBB, 0x2F, 0xEE, 0x7A,
feb11 0:7a1237bd2d13 15 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2, 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
feb11 0:7a1237bd2d13 16 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E, 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03,
feb11 0:7a1237bd2d13 17 0xFF, 0x19, 0x30, 0xB3, 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56, 0xAA, 0xC6,
feb11 0:7a1237bd2d13 18 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6, 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1,
feb11 0:7a1237bd2d13 19 0x45, 0x9D, 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65, 0xE6, 0x2D, 0xA8, 0x02,
feb11 0:7a1237bd2d13 20 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0, 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
feb11 0:7a1237bd2d13 21 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C, 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26,
feb11 0:7a1237bd2d13 22 0x2C, 0x53, 0x0D, 0x6E, 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81, 0x4D, 0x52,
feb11 0:7a1237bd2d13 23 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA, 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A,
feb11 0:7a1237bd2d13 24 0x78, 0x88, 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE, 0x3B, 0x00, 0x1D, 0x39,
feb11 0:7a1237bd2d13 25 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58, 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
feb11 0:7a1237bd2d13 26 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99, 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
feb11 0:7a1237bd2d13 27 };
feb11 0:7a1237bd2d13 28
feb11 0:7a1237bd2d13 29
feb11 0:7a1237bd2d13 30 MD2::MD2():
feb11 0:7a1237bd2d13 31 HashAlgorithm(),
feb11 0:7a1237bd2d13 32 bufferLength(0),
feb11 0:7a1237bd2d13 33 l(0)
feb11 0:7a1237bd2d13 34 {
feb11 0:7a1237bd2d13 35 memset(checksum, 0, 16);
feb11 3:85c6ee25cf3e 36 memset(x, 0, 16);
feb11 0:7a1237bd2d13 37 }
feb11 0:7a1237bd2d13 38
feb11 6:19aa835f2bbb 39 uint8_t MD2::outputSize() const
feb11 6:19aa835f2bbb 40 {
feb11 6:19aa835f2bbb 41 return 16;
feb11 6:19aa835f2bbb 42 }
feb11 6:19aa835f2bbb 43
feb11 6:19aa835f2bbb 44 void MD2::update(uint8_t *data, uint32_t length)
feb11 6:19aa835f2bbb 45 {
feb11 6:19aa835f2bbb 46 if(bufferLength == 0)
feb11 6:19aa835f2bbb 47 {
feb11 6:19aa835f2bbb 48 while(length >= 16)
feb11 6:19aa835f2bbb 49 {
feb11 6:19aa835f2bbb 50 computeBlock(checksum, x, &l, data);
feb11 6:19aa835f2bbb 51 length -= 16;
feb11 6:19aa835f2bbb 52 data += 16;
feb11 6:19aa835f2bbb 53 }
feb11 6:19aa835f2bbb 54 bufferLength = length;
feb11 6:19aa835f2bbb 55 memcpy(buffer, data, length);
feb11 6:19aa835f2bbb 56 }
feb11 6:19aa835f2bbb 57 else if(length < 16-bufferLength)
feb11 6:19aa835f2bbb 58 {
feb11 6:19aa835f2bbb 59 memcpy(&buffer[bufferLength], data, length);
feb11 6:19aa835f2bbb 60 bufferLength += length;
feb11 6:19aa835f2bbb 61 }
feb11 6:19aa835f2bbb 62 else
feb11 6:19aa835f2bbb 63 {
feb11 6:19aa835f2bbb 64 int offset = 16-bufferLength;
feb11 6:19aa835f2bbb 65 memcpy(&buffer[bufferLength], data, offset);
feb11 6:19aa835f2bbb 66 computeBlock(checksum, x, &l, buffer);
feb11 6:19aa835f2bbb 67 data += offset;
feb11 6:19aa835f2bbb 68 length -= offset;
feb11 6:19aa835f2bbb 69 while(length >= 16)
feb11 6:19aa835f2bbb 70 {
feb11 6:19aa835f2bbb 71 computeBlock(checksum, x, &l, data);
feb11 6:19aa835f2bbb 72 data += 16;
feb11 6:19aa835f2bbb 73 length -= 16;
feb11 6:19aa835f2bbb 74 }
feb11 6:19aa835f2bbb 75 bufferLength = length;
feb11 6:19aa835f2bbb 76 memcpy(buffer, &data, length);
feb11 6:19aa835f2bbb 77 }
feb11 6:19aa835f2bbb 78
feb11 6:19aa835f2bbb 79 }
feb11 6:19aa835f2bbb 80
feb11 6:19aa835f2bbb 81 void MD2::finalize(uint8_t *hash)
feb11 6:19aa835f2bbb 82 {
feb11 6:19aa835f2bbb 83 // compute what's left data the buffer
feb11 6:19aa835f2bbb 84 int padding = 16 - bufferLength;
feb11 6:19aa835f2bbb 85 memset(&buffer[bufferLength], padding, padding);
feb11 6:19aa835f2bbb 86 computeBlock(checksum, x, &l, buffer);
feb11 6:19aa835f2bbb 87 computeBlock(checksum, x, &l, checksum);
feb11 6:19aa835f2bbb 88 memcpy(hash, x, 16);
feb11 6:19aa835f2bbb 89
feb11 6:19aa835f2bbb 90 uint32_t *x2 = (uint32_t*)x;
feb11 6:19aa835f2bbb 91 uint32_t *checksum2 = (uint32_t*)checksum;
feb11 6:19aa835f2bbb 92
feb11 6:19aa835f2bbb 93 // reset state
feb11 6:19aa835f2bbb 94 bufferLength = 0;
feb11 6:19aa835f2bbb 95 l = 0;
feb11 6:19aa835f2bbb 96 checksum2[0] = x2[0] = 0;
feb11 6:19aa835f2bbb 97 checksum2[1] = x2[1] = 0;
feb11 6:19aa835f2bbb 98 checksum2[2] = x2[2] = 0;
feb11 6:19aa835f2bbb 99 checksum2[3] = x2[3] = 0;
feb11 6:19aa835f2bbb 100 }
feb11 6:19aa835f2bbb 101
feb11 6:19aa835f2bbb 102 void MD2::computeHash(uint8_t *hash, uint8_t *data, uint32_t length)
feb11 6:19aa835f2bbb 103 {
feb11 6:19aa835f2bbb 104 uint8_t x[48];
feb11 6:19aa835f2bbb 105 uint8_t checksum[16];
feb11 6:19aa835f2bbb 106 uint8_t buffer[16];
feb11 6:19aa835f2bbb 107 memset(x, 0, 16);
feb11 6:19aa835f2bbb 108 memset(checksum, 0, 16);
feb11 6:19aa835f2bbb 109 uint8_t l = 0;
feb11 6:19aa835f2bbb 110 while(length >= 16)
feb11 6:19aa835f2bbb 111 {
feb11 6:19aa835f2bbb 112 computeBlock(checksum, x, &l, data);
feb11 6:19aa835f2bbb 113 length -= 16;
feb11 6:19aa835f2bbb 114 data += 16;
feb11 6:19aa835f2bbb 115 }
feb11 6:19aa835f2bbb 116
feb11 6:19aa835f2bbb 117 memcpy(buffer, data, length);
feb11 6:19aa835f2bbb 118 uint8_t padding = 16-length;
feb11 6:19aa835f2bbb 119 memset(&buffer[length], padding, padding);
feb11 6:19aa835f2bbb 120 computeBlock(checksum, x, &l, buffer);
feb11 6:19aa835f2bbb 121 computeBlock(checksum,x, &l, checksum);
feb11 6:19aa835f2bbb 122 memcpy(hash, x, 16);
feb11 6:19aa835f2bbb 123 }
feb11 6:19aa835f2bbb 124
feb11 1:14a7cea431aa 125 void MD2::computeBlock(uint8_t *checksum2, uint8_t *x2, uint8_t *l2, uint8_t *buffer2)
feb11 0:7a1237bd2d13 126 {
feb11 3:85c6ee25cf3e 127 if(checksum2 != buffer2)
feb11 0:7a1237bd2d13 128 {
feb11 3:85c6ee25cf3e 129 for(int j = 0; j < 16; ++j)
feb11 3:85c6ee25cf3e 130 {
feb11 3:85c6ee25cf3e 131 uint8_t c = buffer2[j];
feb11 3:85c6ee25cf3e 132 *l2 = (checksum2[j] ^= s[c^(*l2)]);
feb11 3:85c6ee25cf3e 133 }
feb11 0:7a1237bd2d13 134 }
feb11 3:85c6ee25cf3e 135
feb11 2:473bac39ae7c 136 uint32_t *x3 = (uint32_t*)x2;
feb11 2:473bac39ae7c 137 uint32_t *buffer3 = (uint32_t*)buffer2;
feb11 2:473bac39ae7c 138
feb11 2:473bac39ae7c 139 x3[4] = buffer3[0];
feb11 2:473bac39ae7c 140 x3[5] = buffer3[1];
feb11 2:473bac39ae7c 141 x3[6] = buffer3[2];
feb11 2:473bac39ae7c 142 x3[7] = buffer3[3];
feb11 2:473bac39ae7c 143 for(int j = 0; j < 4; ++j)
feb11 2:473bac39ae7c 144 x3[8+j] = x3[4+j] ^ x3[j];
feb11 2:473bac39ae7c 145
feb11 0:7a1237bd2d13 146 uint8_t t = 0;
feb11 0:7a1237bd2d13 147
feb11 0:7a1237bd2d13 148 for(int j = 0; j < 18; ++j)
feb11 0:7a1237bd2d13 149 {
feb11 3:85c6ee25cf3e 150 t = (x2[0] ^= s[t]);
feb11 3:85c6ee25cf3e 151 t = (x2[1] ^= s[t]);
feb11 3:85c6ee25cf3e 152 t = (x2[2] ^= s[t]);
feb11 3:85c6ee25cf3e 153 t = (x2[3] ^= s[t]);
feb11 3:85c6ee25cf3e 154 t = (x2[4] ^= s[t]);
feb11 3:85c6ee25cf3e 155 t = (x2[5] ^= s[t]);
feb11 3:85c6ee25cf3e 156 t = (x2[6] ^= s[t]);
feb11 3:85c6ee25cf3e 157 t = (x2[7] ^= s[t]);
feb11 3:85c6ee25cf3e 158 t = (x2[8] ^= s[t]);
feb11 3:85c6ee25cf3e 159 t = (x2[9] ^= s[t]);
feb11 3:85c6ee25cf3e 160 t = (x2[10] ^= s[t]);
feb11 3:85c6ee25cf3e 161 t = (x2[11] ^= s[t]);
feb11 3:85c6ee25cf3e 162 t = (x2[12] ^= s[t]);
feb11 3:85c6ee25cf3e 163 t = (x2[13] ^= s[t]);
feb11 3:85c6ee25cf3e 164 t = (x2[14] ^= s[t]);
feb11 3:85c6ee25cf3e 165 t = (x2[15] ^= s[t]);
feb11 3:85c6ee25cf3e 166 t = (x2[16] ^= s[t]);
feb11 3:85c6ee25cf3e 167 t = (x2[17] ^= s[t]);
feb11 3:85c6ee25cf3e 168 t = (x2[18] ^= s[t]);
feb11 3:85c6ee25cf3e 169 t = (x2[19] ^= s[t]);
feb11 3:85c6ee25cf3e 170 t = (x2[20] ^= s[t]);
feb11 3:85c6ee25cf3e 171 t = (x2[21] ^= s[t]);
feb11 3:85c6ee25cf3e 172 t = (x2[22] ^= s[t]);
feb11 3:85c6ee25cf3e 173 t = (x2[23] ^= s[t]);
feb11 3:85c6ee25cf3e 174 t = (x2[24] ^= s[t]);
feb11 3:85c6ee25cf3e 175 t = (x2[25] ^= s[t]);
feb11 3:85c6ee25cf3e 176 t = (x2[26] ^= s[t]);
feb11 3:85c6ee25cf3e 177 t = (x2[27] ^= s[t]);
feb11 3:85c6ee25cf3e 178 t = (x2[28] ^= s[t]);
feb11 3:85c6ee25cf3e 179 t = (x2[29] ^= s[t]);
feb11 3:85c6ee25cf3e 180 t = (x2[30] ^= s[t]);
feb11 3:85c6ee25cf3e 181 t = (x2[31] ^= s[t]);
feb11 3:85c6ee25cf3e 182 t = (x2[32] ^= s[t]);
feb11 3:85c6ee25cf3e 183 t = (x2[33] ^= s[t]);
feb11 3:85c6ee25cf3e 184 t = (x2[34] ^= s[t]);
feb11 3:85c6ee25cf3e 185 t = (x2[35] ^= s[t]);
feb11 3:85c6ee25cf3e 186 t = (x2[36] ^= s[t]);
feb11 3:85c6ee25cf3e 187 t = (x2[37] ^= s[t]);
feb11 3:85c6ee25cf3e 188 t = (x2[38] ^= s[t]);
feb11 3:85c6ee25cf3e 189 t = (x2[39] ^= s[t]);
feb11 3:85c6ee25cf3e 190 t = (x2[40] ^= s[t]);
feb11 3:85c6ee25cf3e 191 t = (x2[41] ^= s[t]);
feb11 3:85c6ee25cf3e 192 t = (x2[42] ^= s[t]);
feb11 3:85c6ee25cf3e 193 t = (x2[43] ^= s[t]);
feb11 3:85c6ee25cf3e 194 t = (x2[44] ^= s[t]);
feb11 3:85c6ee25cf3e 195 t = (x2[45] ^= s[t]);
feb11 3:85c6ee25cf3e 196 t = (x2[46] ^= s[t]);
feb11 3:85c6ee25cf3e 197 t = (x2[47] ^= s[t]);
feb11 3:85c6ee25cf3e 198
feb11 0:7a1237bd2d13 199 t += j;
feb11 0:7a1237bd2d13 200 }
feb11 6:19aa835f2bbb 201 }