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:
Sat Sep 07 23:47:28 2013 +0000
Revision:
0:7a1237bd2d13
Child:
1:14a7cea431aa
initial import

Who changed what in which revision?

UserRevisionLine numberNew contents of line
feb11 0:7a1237bd2d13 1 #include "MD5.h"
feb11 0:7a1237bd2d13 2 #include <string.h>
feb11 0:7a1237bd2d13 3
feb11 0:7a1237bd2d13 4 static const uint32_t T[] =
feb11 0:7a1237bd2d13 5 {
feb11 0:7a1237bd2d13 6 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
feb11 0:7a1237bd2d13 7 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
feb11 0:7a1237bd2d13 8 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
feb11 0:7a1237bd2d13 9 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
feb11 0:7a1237bd2d13 10 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
feb11 0:7a1237bd2d13 11 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
feb11 0:7a1237bd2d13 12 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
feb11 0:7a1237bd2d13 13 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
feb11 0:7a1237bd2d13 14 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
feb11 0:7a1237bd2d13 15 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
feb11 0:7a1237bd2d13 16 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
feb11 0:7a1237bd2d13 17 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
feb11 0:7a1237bd2d13 18 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
feb11 0:7a1237bd2d13 19 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
feb11 0:7a1237bd2d13 20 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
feb11 0:7a1237bd2d13 21 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
feb11 0:7a1237bd2d13 22 };
feb11 0:7a1237bd2d13 23
feb11 0:7a1237bd2d13 24 static const uint32_t A = 0x67452301;
feb11 0:7a1237bd2d13 25 static const uint32_t B = 0xefcdab89;
feb11 0:7a1237bd2d13 26 static const uint32_t C = 0x98badcfe;
feb11 0:7a1237bd2d13 27 static const uint32_t D = 0x10325476;
feb11 0:7a1237bd2d13 28
feb11 0:7a1237bd2d13 29 static uint32_t F(uint32_t x, uint32_t y, uint32_t z)
feb11 0:7a1237bd2d13 30 {
feb11 0:7a1237bd2d13 31 return (x & y) | ((~x) & z);
feb11 0:7a1237bd2d13 32 }
feb11 0:7a1237bd2d13 33
feb11 0:7a1237bd2d13 34 static uint32_t G(uint32_t x, uint32_t y, uint32_t z)
feb11 0:7a1237bd2d13 35 {
feb11 0:7a1237bd2d13 36 return (x & z) | (y & (~z));
feb11 0:7a1237bd2d13 37 }
feb11 0:7a1237bd2d13 38
feb11 0:7a1237bd2d13 39 static uint32_t H(uint32_t x, uint32_t y, uint32_t z)
feb11 0:7a1237bd2d13 40 {
feb11 0:7a1237bd2d13 41 return x ^ y ^ z;
feb11 0:7a1237bd2d13 42 }
feb11 0:7a1237bd2d13 43
feb11 0:7a1237bd2d13 44 static uint32_t I(uint32_t x, uint32_t y, uint32_t z)
feb11 0:7a1237bd2d13 45 {
feb11 0:7a1237bd2d13 46 return y ^ (x | (~z));
feb11 0:7a1237bd2d13 47 }
feb11 0:7a1237bd2d13 48
feb11 0:7a1237bd2d13 49 static uint32_t rotLeft(uint32_t w, uint8_t s)
feb11 0:7a1237bd2d13 50 {
feb11 0:7a1237bd2d13 51 return (w << s) | (w >> (32-s));
feb11 0:7a1237bd2d13 52 }
feb11 0:7a1237bd2d13 53
feb11 0:7a1237bd2d13 54 #define ROUND1(a,b,c,d,k,s,i) \
feb11 0:7a1237bd2d13 55 a += F(b,c,d) + x[k] + T[i-1]; \
feb11 0:7a1237bd2d13 56 a = rotLeft(a,s);\
feb11 0:7a1237bd2d13 57 a += b;
feb11 0:7a1237bd2d13 58 #define ROUND2(a,b,c,d,k,s,i) \
feb11 0:7a1237bd2d13 59 a += G(b,c,d) + x[k] + T[i-1]; \
feb11 0:7a1237bd2d13 60 a = rotLeft(a,s);\
feb11 0:7a1237bd2d13 61 a += b;
feb11 0:7a1237bd2d13 62 #define ROUND3(a,b,c,d,k,s,i) \
feb11 0:7a1237bd2d13 63 a += H(b,c,d) + x[k] + T[i-1]; \
feb11 0:7a1237bd2d13 64 a = rotLeft(a,s);\
feb11 0:7a1237bd2d13 65 a += b;
feb11 0:7a1237bd2d13 66 #define ROUND4(a,b,c,d,k,s,i) \
feb11 0:7a1237bd2d13 67 a += I(b,c,d) + x[k] + T[i-1]; \
feb11 0:7a1237bd2d13 68 a = rotLeft(a,s);\
feb11 0:7a1237bd2d13 69 a += b;
feb11 0:7a1237bd2d13 70
feb11 0:7a1237bd2d13 71
feb11 0:7a1237bd2d13 72 MD5::MD5():
feb11 0:7a1237bd2d13 73 HashAlgorithm(),
feb11 0:7a1237bd2d13 74 a(A),
feb11 0:7a1237bd2d13 75 b(B),
feb11 0:7a1237bd2d13 76 c(C),
feb11 0:7a1237bd2d13 77 d(D),
feb11 0:7a1237bd2d13 78 totalBufferLength(0),
feb11 0:7a1237bd2d13 79 buffer(),
feb11 0:7a1237bd2d13 80 bufferLength(0)
feb11 0:7a1237bd2d13 81 {
feb11 0:7a1237bd2d13 82 }
feb11 0:7a1237bd2d13 83
feb11 0:7a1237bd2d13 84 uint8_t MD5::outputSize() const
feb11 0:7a1237bd2d13 85 {
feb11 0:7a1237bd2d13 86 return 16;
feb11 0:7a1237bd2d13 87 }
feb11 0:7a1237bd2d13 88
feb11 0:7a1237bd2d13 89 void MD5::add(uint8_t *in, uint32_t length)
feb11 0:7a1237bd2d13 90 {
feb11 0:7a1237bd2d13 91 if(length < 64-bufferLength)
feb11 0:7a1237bd2d13 92 {
feb11 0:7a1237bd2d13 93 memcpy(&buffer[bufferLength], in, length);
feb11 0:7a1237bd2d13 94 bufferLength += length;
feb11 0:7a1237bd2d13 95 totalBufferLength += length;
feb11 0:7a1237bd2d13 96 return;
feb11 0:7a1237bd2d13 97 }
feb11 0:7a1237bd2d13 98 int offset = 64-bufferLength;
feb11 0:7a1237bd2d13 99 memcpy(&buffer[bufferLength], in, offset);
feb11 0:7a1237bd2d13 100 uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d;
feb11 0:7a1237bd2d13 101 computeRounds(&a, &b, &c, &d, buffer);
feb11 0:7a1237bd2d13 102 a += tmpA;
feb11 0:7a1237bd2d13 103 b += tmpB;
feb11 0:7a1237bd2d13 104 c += tmpC;
feb11 0:7a1237bd2d13 105 d += tmpD;
feb11 0:7a1237bd2d13 106 while(length-offset > 64)
feb11 0:7a1237bd2d13 107 {
feb11 0:7a1237bd2d13 108 memcpy(buffer, &in[offset], 64);
feb11 0:7a1237bd2d13 109 tmpA = a;
feb11 0:7a1237bd2d13 110 tmpB = b;
feb11 0:7a1237bd2d13 111 tmpC = c;
feb11 0:7a1237bd2d13 112 tmpD = d;
feb11 0:7a1237bd2d13 113 computeRounds(&a, &b, &c, &d, buffer);
feb11 0:7a1237bd2d13 114 a += tmpA;
feb11 0:7a1237bd2d13 115 b += tmpB;
feb11 0:7a1237bd2d13 116 c += tmpC;
feb11 0:7a1237bd2d13 117 d += tmpD;
feb11 0:7a1237bd2d13 118 offset += 64;
feb11 0:7a1237bd2d13 119 }
feb11 0:7a1237bd2d13 120 if(offset > length)
feb11 0:7a1237bd2d13 121 offset -= 64;
feb11 0:7a1237bd2d13 122 bufferLength = length - offset;
feb11 0:7a1237bd2d13 123 memcpy(buffer, &in[offset], bufferLength);
feb11 0:7a1237bd2d13 124 totalBufferLength += length;
feb11 0:7a1237bd2d13 125 }
feb11 0:7a1237bd2d13 126
feb11 0:7a1237bd2d13 127 void MD5::computeDigest(uint8_t *digest)
feb11 0:7a1237bd2d13 128 {
feb11 0:7a1237bd2d13 129 uint16_t padding;
feb11 0:7a1237bd2d13 130 if(totalBufferLength % 64 < 56)
feb11 0:7a1237bd2d13 131 padding = 56 - (totalBufferLength % 64);
feb11 0:7a1237bd2d13 132 else
feb11 0:7a1237bd2d13 133 padding = 56 + (64 - (totalBufferLength % 64));
feb11 0:7a1237bd2d13 134 uint8_t val = 0x80;
feb11 0:7a1237bd2d13 135 add(&val, 1);
feb11 0:7a1237bd2d13 136 val = 0;
feb11 0:7a1237bd2d13 137 for(int i = 0; i < padding-1; ++i)
feb11 0:7a1237bd2d13 138 add(&val,1);
feb11 0:7a1237bd2d13 139 totalBufferLength -= padding;
feb11 0:7a1237bd2d13 140 uint64_t lengthBit = totalBufferLength * 8;
feb11 0:7a1237bd2d13 141 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 142 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 0:7a1237bd2d13 143 add((uint8_t*)&lengthBitLow,4);
feb11 0:7a1237bd2d13 144 add((uint8_t*)&lengthBitHigh,4);
feb11 0:7a1237bd2d13 145
feb11 0:7a1237bd2d13 146 memcpy(digest, &a, 4);
feb11 0:7a1237bd2d13 147 memcpy(&digest[4], &b, 4);
feb11 0:7a1237bd2d13 148 memcpy(&digest[8], &c, 4);
feb11 0:7a1237bd2d13 149 memcpy(&digest[12], &d, 4);
feb11 0:7a1237bd2d13 150 // reset state
feb11 0:7a1237bd2d13 151 a = A;
feb11 0:7a1237bd2d13 152 b = B;
feb11 0:7a1237bd2d13 153 c = C;
feb11 0:7a1237bd2d13 154 d = D;
feb11 0:7a1237bd2d13 155 totalBufferLength = 0;
feb11 0:7a1237bd2d13 156 bufferLength = 0;
feb11 0:7a1237bd2d13 157 }
feb11 0:7a1237bd2d13 158
feb11 0:7a1237bd2d13 159 void MD5::computeRounds(uint32_t *a2, uint32_t *b2, uint32_t *c2, uint32_t *d2, uint8_t *buffer)
feb11 0:7a1237bd2d13 160 {
feb11 0:7a1237bd2d13 161 uint32_t a = *a2, b = *b2, c = *c2, d = *d2;
feb11 0:7a1237bd2d13 162 uint32_t x[16];
feb11 0:7a1237bd2d13 163 for(int j = 0; j < 16; ++j)
feb11 0:7a1237bd2d13 164 memcpy(&x[j], &buffer[j*4], 4);
feb11 0:7a1237bd2d13 165
feb11 0:7a1237bd2d13 166 // Round 1
feb11 0:7a1237bd2d13 167 ROUND1(a,b,c,d,0,7,1); ROUND1(d,a,b,c,1,12,2); ROUND1(c,d,a,b,2,17,3); ROUND1(b,c,d,a,3,22,4);
feb11 0:7a1237bd2d13 168 ROUND1(a,b,c,d,4,7,5); ROUND1(d,a,b,c,5,12,6); ROUND1(c,d,a,b,6,17,7); ROUND1(b,c,d,a,7,22,8);
feb11 0:7a1237bd2d13 169 ROUND1(a,b,c,d,8,7,9); ROUND1(d,a,b,c,9,12,10); ROUND1(c,d,a,b,10,17,11); ROUND1(b,c,d,a,11,22,12);
feb11 0:7a1237bd2d13 170 ROUND1(a,b,c,d,12,7,13); ROUND1(d,a,b,c,13,12,14); ROUND1(c,d,a,b,14,17,15); ROUND1(b,c,d,a,15,22,16);
feb11 0:7a1237bd2d13 171
feb11 0:7a1237bd2d13 172 // Round 2
feb11 0:7a1237bd2d13 173 ROUND2(a,b,c,d,1,5,17); ROUND2(d,a,b,c,6,9,18); ROUND2(c,d,a,b,11,14,19); ROUND2(b,c,d,a,0,20,20);
feb11 0:7a1237bd2d13 174 ROUND2(a,b,c,d,5,5,21); ROUND2(d,a,b,c,10,9,22); ROUND2(c,d,a,b,15,14,23); ROUND2(b,c,d,a,4,20,24);
feb11 0:7a1237bd2d13 175 ROUND2(a,b,c,d,9,5,25); ROUND2(d,a,b,c,14,9,26); ROUND2(c,d,a,b,3,14,27); ROUND2(b,c,d,a,8,20,28);
feb11 0:7a1237bd2d13 176 ROUND2(a,b,c,d,13,5,29); ROUND2(d,a,b,c,2,9,30); ROUND2(c,d,a,b,7,14,31); ROUND2(b,c,d,a,12,20,32);
feb11 0:7a1237bd2d13 177
feb11 0:7a1237bd2d13 178 // Round 3
feb11 0:7a1237bd2d13 179 ROUND3(a,b,c,d,5,4,33); ROUND3(d,a,b,c,8,11,34); ROUND3(c,d,a,b,11,16,35); ROUND3(b,c,d,a,14,23,36);
feb11 0:7a1237bd2d13 180 ROUND3(a,b,c,d,1,4,37); ROUND3(d,a,b,c,4,11,38); ROUND3(c,d,a,b,7,16,39); ROUND3(b,c,d,a,10,23,40);
feb11 0:7a1237bd2d13 181 ROUND3(a,b,c,d,13,4,41); ROUND3(d,a,b,c,0,11,42); ROUND3(c,d,a,b,3,16,43); ROUND3(b,c,d,a,6,23,44);
feb11 0:7a1237bd2d13 182 ROUND3(a,b,c,d,9,4,45); ROUND3(d,a,b,c,12,11,46); ROUND3(c,d,a,b,15,16,47); ROUND3(b,c,d,a,2,23,48);
feb11 0:7a1237bd2d13 183
feb11 0:7a1237bd2d13 184 // Round 4
feb11 0:7a1237bd2d13 185 ROUND4(a,b,c,d,0,6,49); ROUND4(d,a,b,c,7,10,50); ROUND4(c,d,a,b,14,15,51); ROUND4(b,c,d,a,5,21,52);
feb11 0:7a1237bd2d13 186 ROUND4(a,b,c,d,12,6,53); ROUND4(d,a,b,c,3,10,54); ROUND4(c,d,a,b,10,15,55); ROUND4(b,c,d,a,1,21,56);
feb11 0:7a1237bd2d13 187 ROUND4(a,b,c,d,8,6,57); ROUND4(d,a,b,c,15,10,58); ROUND4(c,d,a,b,6,15,59); ROUND4(b,c,d,a,13,21,60);
feb11 0:7a1237bd2d13 188 ROUND4(a,b,c,d,4,6,61); ROUND4(d,a,b,c,11,10,62); ROUND4(c,d,a,b,2,15,63); ROUND4(b,c,d,a,9,21,64);
feb11 0:7a1237bd2d13 189
feb11 0:7a1237bd2d13 190 *a2 = a;
feb11 0:7a1237bd2d13 191 *b2 = b;
feb11 0:7a1237bd2d13 192 *c2 = c;
feb11 0:7a1237bd2d13 193 *d2 = d;
feb11 0:7a1237bd2d13 194 }
feb11 0:7a1237bd2d13 195
feb11 0:7a1237bd2d13 196 void MD5::computeDigest(uint8_t *digest, uint8_t *msg, uint32_t length)
feb11 0:7a1237bd2d13 197 {
feb11 0:7a1237bd2d13 198 uint16_t padding;
feb11 0:7a1237bd2d13 199 if(length % 64 < 56)
feb11 0:7a1237bd2d13 200 padding = 56 - (length % 64);
feb11 0:7a1237bd2d13 201 else
feb11 0:7a1237bd2d13 202 padding = 56 + (64 - (length % 64));
feb11 0:7a1237bd2d13 203 uint32_t totalLength = length + padding + 8;
feb11 0:7a1237bd2d13 204 uint8_t *buffer = new uint8_t[totalLength];
feb11 0:7a1237bd2d13 205 memcpy(buffer, msg, length);
feb11 0:7a1237bd2d13 206 buffer[length] = 0x80;
feb11 0:7a1237bd2d13 207 memset(&buffer[length+1], 0, padding-1);
feb11 0:7a1237bd2d13 208 uint64_t lengthBit = length * 8;
feb11 0:7a1237bd2d13 209 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 210 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 0:7a1237bd2d13 211 memcpy(&buffer[length+padding], &lengthBitLow, 4);
feb11 0:7a1237bd2d13 212 memcpy(&buffer[length+padding+4], &lengthBitHigh, 4);
feb11 0:7a1237bd2d13 213
feb11 0:7a1237bd2d13 214 uint32_t a = A, b = B, c = C, d = D;
feb11 0:7a1237bd2d13 215 for(int i = 0; i < totalLength/64; ++i)
feb11 0:7a1237bd2d13 216 {
feb11 0:7a1237bd2d13 217 uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d;
feb11 0:7a1237bd2d13 218 computeRounds(&a, &b, &c, &d, &buffer[64*i]);
feb11 0:7a1237bd2d13 219
feb11 0:7a1237bd2d13 220 a += tmpA;
feb11 0:7a1237bd2d13 221 b += tmpB;
feb11 0:7a1237bd2d13 222 c += tmpC;
feb11 0:7a1237bd2d13 223 d += tmpD;
feb11 0:7a1237bd2d13 224 }
feb11 0:7a1237bd2d13 225 delete[] buffer;
feb11 0:7a1237bd2d13 226
feb11 0:7a1237bd2d13 227 memcpy(digest, &a, 4);
feb11 0:7a1237bd2d13 228 memcpy(&digest[4], &b, 4);
feb11 0:7a1237bd2d13 229 memcpy(&digest[8], &c, 4);
feb11 0:7a1237bd2d13 230 memcpy(&digest[12], &d, 4);
feb11 0:7a1237bd2d13 231 }