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 14 18:21:32 2013 +0000
Revision:
7:2dbbdfb08123
Parent:
MD5.cpp@6:19aa835f2bbb
Child:
10:bc9c23aa3870
added DES (not tested yet)

Who changed what in which revision?

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