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 10:18:57 2013 +0000
Revision:
4:0da19393bd57
Parent:
3:85c6ee25cf3e
Child:
5:06cd9c8afa0b
improved performance of SHA-2 (32 & 64bits)

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 0:7a1237bd2d13 53 void MD5::add(uint8_t *in, uint32_t length)
feb11 0:7a1237bd2d13 54 {
feb11 0:7a1237bd2d13 55 if(length < 64-bufferLength)
feb11 0:7a1237bd2d13 56 {
feb11 0:7a1237bd2d13 57 memcpy(&buffer[bufferLength], in, 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 0:7a1237bd2d13 63 memcpy(&buffer[bufferLength], in, offset);
feb11 0:7a1237bd2d13 64 computeRounds(&a, &b, &c, &d, buffer);
feb11 0:7a1237bd2d13 65 while(length-offset > 64)
feb11 0:7a1237bd2d13 66 {
feb11 0:7a1237bd2d13 67 memcpy(buffer, &in[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 0:7a1237bd2d13 74 memcpy(buffer, &in[offset], bufferLength);
feb11 0:7a1237bd2d13 75 totalBufferLength += length;
feb11 0:7a1237bd2d13 76 }
feb11 0:7a1237bd2d13 77
feb11 0:7a1237bd2d13 78 void MD5::computeDigest(uint8_t *digest)
feb11 0:7a1237bd2d13 79 {
feb11 0:7a1237bd2d13 80 uint16_t padding;
feb11 0:7a1237bd2d13 81 if(totalBufferLength % 64 < 56)
feb11 0:7a1237bd2d13 82 padding = 56 - (totalBufferLength % 64);
feb11 0:7a1237bd2d13 83 else
feb11 0:7a1237bd2d13 84 padding = 56 + (64 - (totalBufferLength % 64));
feb11 3:85c6ee25cf3e 85 buffer[bufferLength++] = 0x80;
feb11 3:85c6ee25cf3e 86 padding--;
feb11 3:85c6ee25cf3e 87 if(padding+bufferLength == 56)
feb11 3:85c6ee25cf3e 88 memset(&buffer[bufferLength], 0, padding);
feb11 3:85c6ee25cf3e 89 else
feb11 3:85c6ee25cf3e 90 {
feb11 3:85c6ee25cf3e 91 memset(&buffer[bufferLength], 0, 64-bufferLength);
feb11 3:85c6ee25cf3e 92 computeRounds(&a, &b, &c, &d, buffer);
feb11 3:85c6ee25cf3e 93 memset(buffer, 0, bufferLength);
feb11 3:85c6ee25cf3e 94 }
feb11 3:85c6ee25cf3e 95 uint64_t lengthBit = totalBufferLength << 3;
feb11 0:7a1237bd2d13 96 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 97 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 3:85c6ee25cf3e 98 memcpy(&buffer[56], &lengthBitLow, 4);
feb11 3:85c6ee25cf3e 99 memcpy(&buffer[60], &lengthBitHigh, 4);
feb11 3:85c6ee25cf3e 100 computeRounds(&a, &b, &c, &d, buffer);
feb11 0:7a1237bd2d13 101
feb11 0:7a1237bd2d13 102 memcpy(digest, &a, 4);
feb11 0:7a1237bd2d13 103 memcpy(&digest[4], &b, 4);
feb11 0:7a1237bd2d13 104 memcpy(&digest[8], &c, 4);
feb11 0:7a1237bd2d13 105 memcpy(&digest[12], &d, 4);
feb11 0:7a1237bd2d13 106 // reset state
feb11 0:7a1237bd2d13 107 a = A;
feb11 0:7a1237bd2d13 108 b = B;
feb11 0:7a1237bd2d13 109 c = C;
feb11 0:7a1237bd2d13 110 d = D;
feb11 0:7a1237bd2d13 111 totalBufferLength = 0;
feb11 0:7a1237bd2d13 112 bufferLength = 0;
feb11 0:7a1237bd2d13 113 }
feb11 0:7a1237bd2d13 114
feb11 0:7a1237bd2d13 115 void MD5::computeRounds(uint32_t *a2, uint32_t *b2, uint32_t *c2, uint32_t *d2, uint8_t *buffer)
feb11 0:7a1237bd2d13 116 {
feb11 1:14a7cea431aa 117
feb11 0:7a1237bd2d13 118 uint32_t a = *a2, b = *b2, c = *c2, d = *d2;
feb11 1:14a7cea431aa 119 uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d;
feb11 1:14a7cea431aa 120
feb11 3:85c6ee25cf3e 121 uint32_t *x = (uint32_t*)buffer;
feb11 3:85c6ee25cf3e 122
feb11 0:7a1237bd2d13 123 // Round 1
feb11 3:85c6ee25cf3e 124 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 125 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 126 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 127 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 128
feb11 3:85c6ee25cf3e 129
feb11 0:7a1237bd2d13 130 // Round 2
feb11 3:85c6ee25cf3e 131 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 132 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 133 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 134 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 135
feb11 3:85c6ee25cf3e 136
feb11 0:7a1237bd2d13 137 // Round 3
feb11 3:85c6ee25cf3e 138 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 139 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 140 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 141 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 142
feb11 3:85c6ee25cf3e 143
feb11 0:7a1237bd2d13 144 // Round 4
feb11 3:85c6ee25cf3e 145 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 146 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 147 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 148 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 149
feb11 3:85c6ee25cf3e 150 *a2 = a + tmpA;
feb11 3:85c6ee25cf3e 151 *b2 = b + tmpB;
feb11 3:85c6ee25cf3e 152 *c2 = c + tmpC;
feb11 3:85c6ee25cf3e 153 *d2 = d + tmpD;
feb11 0:7a1237bd2d13 154 }
feb11 0:7a1237bd2d13 155
feb11 0:7a1237bd2d13 156 void MD5::computeDigest(uint8_t *digest, uint8_t *msg, uint32_t length)
feb11 0:7a1237bd2d13 157 {
feb11 3:85c6ee25cf3e 158 uint64_t lengthBit = length << 3;
feb11 0:7a1237bd2d13 159 uint16_t padding;
feb11 0:7a1237bd2d13 160 if(length % 64 < 56)
feb11 0:7a1237bd2d13 161 padding = 56 - (length % 64);
feb11 0:7a1237bd2d13 162 else
feb11 0:7a1237bd2d13 163 padding = 56 + (64 - (length % 64));
feb11 1:14a7cea431aa 164
feb11 1:14a7cea431aa 165 uint32_t a = A, b = B, c = C, d = D;
feb11 3:85c6ee25cf3e 166 while(length >= 64)
feb11 1:14a7cea431aa 167 {
feb11 3:85c6ee25cf3e 168 computeRounds(&a, &b, &c, &d, msg);
feb11 3:85c6ee25cf3e 169 msg += 64;
feb11 3:85c6ee25cf3e 170 length -= 64;
feb11 1:14a7cea431aa 171 }
feb11 1:14a7cea431aa 172 uint8_t buffer[64];
feb11 3:85c6ee25cf3e 173 memcpy(buffer, msg, length);
feb11 3:85c6ee25cf3e 174 buffer[length++] = 0x80;
feb11 1:14a7cea431aa 175 padding--;
feb11 3:85c6ee25cf3e 176 if(padding+length == 56)
feb11 3:85c6ee25cf3e 177 memset(&buffer[length], 0, padding);
feb11 3:85c6ee25cf3e 178 else
feb11 1:14a7cea431aa 179 {
feb11 3:85c6ee25cf3e 180 memset(&buffer[length], 0, 64-length);
feb11 3:85c6ee25cf3e 181 computeRounds(&a, &b, &c, &d, msg);
feb11 3:85c6ee25cf3e 182 memset(buffer, 0, length);
feb11 1:14a7cea431aa 183 }
feb11 3:85c6ee25cf3e 184
feb11 0:7a1237bd2d13 185 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 186 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 1:14a7cea431aa 187 memcpy(&buffer[56], &lengthBitLow, 4);
feb11 1:14a7cea431aa 188 memcpy(&buffer[60], &lengthBitHigh, 4);
feb11 0:7a1237bd2d13 189
feb11 1:14a7cea431aa 190 computeRounds(&a, &b, &c, &d, buffer);
feb11 1:14a7cea431aa 191
feb11 0:7a1237bd2d13 192 memcpy(digest, &a, 4);
feb11 0:7a1237bd2d13 193 memcpy(&digest[4], &b, 4);
feb11 0:7a1237bd2d13 194 memcpy(&digest[8], &c, 4);
feb11 0:7a1237bd2d13 195 memcpy(&digest[12], &d, 4);
feb11 0:7a1237bd2d13 196 }