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:
Wed Sep 11 17:22:40 2013 +0000
Revision:
3:85c6ee25cf3e
Parent:
1:14a7cea431aa
Child:
4:0da19393bd57
improved speed of MD2, MD5, SHA-1 and SHA-2 (32bits)

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 A = 0x67452301;
feb11 0:7a1237bd2d13 5 static const uint32_t B = 0xefcdab89;
feb11 0:7a1237bd2d13 6 static const uint32_t C = 0x98badcfe;
feb11 0:7a1237bd2d13 7 static const uint32_t D = 0x10325476;
feb11 0:7a1237bd2d13 8
feb11 0:7a1237bd2d13 9
feb11 3:85c6ee25cf3e 10 #define F(X,Y,Z) (((X) & (Y)) | ((~(X)) & (Z)))
feb11 3:85c6ee25cf3e 11 #define G(X,Y,Z) (((X) & (Z)) | ((Y) & (~(Z))))
feb11 3:85c6ee25cf3e 12 #define H(X,Y,Z) ((X) ^ (Y) ^ (Z))
feb11 3:85c6ee25cf3e 13 #define I(X,Y,Z) ((Y) ^ ((X) | (~(Z))))
feb11 0:7a1237bd2d13 14
feb11 3:85c6ee25cf3e 15 #define ROTL(W,N) (((W) << N) | ((W) >> (32-N)))
feb11 0:7a1237bd2d13 16
feb11 3:85c6ee25cf3e 17 #define ROUND1(a,b,c,d,x,s,t) \
feb11 3:85c6ee25cf3e 18 a = ROTL(a + F(b,c,d) + x + t,s) + b;
feb11 3:85c6ee25cf3e 19
feb11 3:85c6ee25cf3e 20 #define ROUND2(a,b,c,d,x,s,t) \
feb11 3:85c6ee25cf3e 21 a = ROTL(a + G(b,c,d) + x + t,s) + b;
feb11 0:7a1237bd2d13 22
feb11 3:85c6ee25cf3e 23 #define ROUND3(a,b,c,d,x,s,t) \
feb11 3:85c6ee25cf3e 24 a = ROTL(a + H(b,c,d) + x + t,s) + b;
feb11 3:85c6ee25cf3e 25
feb11 3:85c6ee25cf3e 26 #define ROUND4(a,b,c,d,x,s,t) \
feb11 3:85c6ee25cf3e 27 a = ROTL(a + I(b,c,d) + x + t,s) + b;
feb11 3:85c6ee25cf3e 28
feb11 0:7a1237bd2d13 29
feb11 0:7a1237bd2d13 30
feb11 0:7a1237bd2d13 31 MD5::MD5():
feb11 0:7a1237bd2d13 32 HashAlgorithm(),
feb11 0:7a1237bd2d13 33 a(A),
feb11 0:7a1237bd2d13 34 b(B),
feb11 0:7a1237bd2d13 35 c(C),
feb11 0:7a1237bd2d13 36 d(D),
feb11 0:7a1237bd2d13 37 totalBufferLength(0),
feb11 0:7a1237bd2d13 38 buffer(),
feb11 0:7a1237bd2d13 39 bufferLength(0)
feb11 0:7a1237bd2d13 40 {
feb11 0:7a1237bd2d13 41 }
feb11 0:7a1237bd2d13 42
feb11 0:7a1237bd2d13 43 uint8_t MD5::outputSize() const
feb11 0:7a1237bd2d13 44 {
feb11 0:7a1237bd2d13 45 return 16;
feb11 0:7a1237bd2d13 46 }
feb11 0:7a1237bd2d13 47
feb11 0:7a1237bd2d13 48 void MD5::add(uint8_t *in, uint32_t length)
feb11 0:7a1237bd2d13 49 {
feb11 0:7a1237bd2d13 50 if(length < 64-bufferLength)
feb11 0:7a1237bd2d13 51 {
feb11 0:7a1237bd2d13 52 memcpy(&buffer[bufferLength], in, length);
feb11 0:7a1237bd2d13 53 bufferLength += length;
feb11 0:7a1237bd2d13 54 totalBufferLength += length;
feb11 0:7a1237bd2d13 55 return;
feb11 0:7a1237bd2d13 56 }
feb11 0:7a1237bd2d13 57 int offset = 64-bufferLength;
feb11 0:7a1237bd2d13 58 memcpy(&buffer[bufferLength], in, offset);
feb11 0:7a1237bd2d13 59 computeRounds(&a, &b, &c, &d, buffer);
feb11 0:7a1237bd2d13 60 while(length-offset > 64)
feb11 0:7a1237bd2d13 61 {
feb11 0:7a1237bd2d13 62 memcpy(buffer, &in[offset], 64);
feb11 0:7a1237bd2d13 63 computeRounds(&a, &b, &c, &d, buffer);
feb11 0:7a1237bd2d13 64 offset += 64;
feb11 0:7a1237bd2d13 65 }
feb11 0:7a1237bd2d13 66 if(offset > length)
feb11 0:7a1237bd2d13 67 offset -= 64;
feb11 0:7a1237bd2d13 68 bufferLength = length - offset;
feb11 0:7a1237bd2d13 69 memcpy(buffer, &in[offset], bufferLength);
feb11 0:7a1237bd2d13 70 totalBufferLength += length;
feb11 0:7a1237bd2d13 71 }
feb11 0:7a1237bd2d13 72
feb11 0:7a1237bd2d13 73 void MD5::computeDigest(uint8_t *digest)
feb11 0:7a1237bd2d13 74 {
feb11 0:7a1237bd2d13 75 uint16_t padding;
feb11 0:7a1237bd2d13 76 if(totalBufferLength % 64 < 56)
feb11 0:7a1237bd2d13 77 padding = 56 - (totalBufferLength % 64);
feb11 0:7a1237bd2d13 78 else
feb11 0:7a1237bd2d13 79 padding = 56 + (64 - (totalBufferLength % 64));
feb11 3:85c6ee25cf3e 80 buffer[bufferLength++] = 0x80;
feb11 3:85c6ee25cf3e 81 padding--;
feb11 3:85c6ee25cf3e 82 if(padding+bufferLength == 56)
feb11 3:85c6ee25cf3e 83 memset(&buffer[bufferLength], 0, padding);
feb11 3:85c6ee25cf3e 84 else
feb11 3:85c6ee25cf3e 85 {
feb11 3:85c6ee25cf3e 86 memset(&buffer[bufferLength], 0, 64-bufferLength);
feb11 3:85c6ee25cf3e 87 computeRounds(&a, &b, &c, &d, buffer);
feb11 3:85c6ee25cf3e 88 memset(buffer, 0, bufferLength);
feb11 3:85c6ee25cf3e 89 }
feb11 3:85c6ee25cf3e 90 uint64_t lengthBit = totalBufferLength << 3;
feb11 0:7a1237bd2d13 91 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 92 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 3:85c6ee25cf3e 93 memcpy(&buffer[56], &lengthBitLow, 4);
feb11 3:85c6ee25cf3e 94 memcpy(&buffer[60], &lengthBitHigh, 4);
feb11 3:85c6ee25cf3e 95 computeRounds(&a, &b, &c, &d, buffer);
feb11 0:7a1237bd2d13 96
feb11 0:7a1237bd2d13 97 memcpy(digest, &a, 4);
feb11 0:7a1237bd2d13 98 memcpy(&digest[4], &b, 4);
feb11 0:7a1237bd2d13 99 memcpy(&digest[8], &c, 4);
feb11 0:7a1237bd2d13 100 memcpy(&digest[12], &d, 4);
feb11 0:7a1237bd2d13 101 // reset state
feb11 0:7a1237bd2d13 102 a = A;
feb11 0:7a1237bd2d13 103 b = B;
feb11 0:7a1237bd2d13 104 c = C;
feb11 0:7a1237bd2d13 105 d = D;
feb11 0:7a1237bd2d13 106 totalBufferLength = 0;
feb11 0:7a1237bd2d13 107 bufferLength = 0;
feb11 0:7a1237bd2d13 108 }
feb11 0:7a1237bd2d13 109
feb11 0:7a1237bd2d13 110 void MD5::computeRounds(uint32_t *a2, uint32_t *b2, uint32_t *c2, uint32_t *d2, uint8_t *buffer)
feb11 0:7a1237bd2d13 111 {
feb11 1:14a7cea431aa 112
feb11 0:7a1237bd2d13 113 uint32_t a = *a2, b = *b2, c = *c2, d = *d2;
feb11 1:14a7cea431aa 114 uint32_t tmpA = a, tmpB = b, tmpC = c, tmpD = d;
feb11 1:14a7cea431aa 115
feb11 3:85c6ee25cf3e 116 uint32_t *x = (uint32_t*)buffer;
feb11 3:85c6ee25cf3e 117
feb11 0:7a1237bd2d13 118 // Round 1
feb11 3:85c6ee25cf3e 119 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 120 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 121 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 122 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 123
feb11 3:85c6ee25cf3e 124
feb11 0:7a1237bd2d13 125 // Round 2
feb11 3:85c6ee25cf3e 126 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 127 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 128 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 129 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 130
feb11 3:85c6ee25cf3e 131
feb11 0:7a1237bd2d13 132 // Round 3
feb11 3:85c6ee25cf3e 133 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 134 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 135 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 136 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 137
feb11 3:85c6ee25cf3e 138
feb11 0:7a1237bd2d13 139 // Round 4
feb11 3:85c6ee25cf3e 140 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 141 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 142 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 143 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 144
feb11 3:85c6ee25cf3e 145 *a2 = a + tmpA;
feb11 3:85c6ee25cf3e 146 *b2 = b + tmpB;
feb11 3:85c6ee25cf3e 147 *c2 = c + tmpC;
feb11 3:85c6ee25cf3e 148 *d2 = d + tmpD;
feb11 0:7a1237bd2d13 149 }
feb11 0:7a1237bd2d13 150
feb11 0:7a1237bd2d13 151 void MD5::computeDigest(uint8_t *digest, uint8_t *msg, uint32_t length)
feb11 0:7a1237bd2d13 152 {
feb11 3:85c6ee25cf3e 153 uint64_t lengthBit = length << 3;
feb11 0:7a1237bd2d13 154 uint16_t padding;
feb11 0:7a1237bd2d13 155 if(length % 64 < 56)
feb11 0:7a1237bd2d13 156 padding = 56 - (length % 64);
feb11 0:7a1237bd2d13 157 else
feb11 0:7a1237bd2d13 158 padding = 56 + (64 - (length % 64));
feb11 1:14a7cea431aa 159
feb11 1:14a7cea431aa 160 uint32_t a = A, b = B, c = C, d = D;
feb11 3:85c6ee25cf3e 161 while(length >= 64)
feb11 1:14a7cea431aa 162 {
feb11 3:85c6ee25cf3e 163 computeRounds(&a, &b, &c, &d, msg);
feb11 3:85c6ee25cf3e 164 msg += 64;
feb11 3:85c6ee25cf3e 165 length -= 64;
feb11 1:14a7cea431aa 166 }
feb11 1:14a7cea431aa 167 uint8_t buffer[64];
feb11 3:85c6ee25cf3e 168 memcpy(buffer, msg, length);
feb11 3:85c6ee25cf3e 169 buffer[length++] = 0x80;
feb11 1:14a7cea431aa 170 padding--;
feb11 3:85c6ee25cf3e 171 if(padding+length == 56)
feb11 3:85c6ee25cf3e 172 memset(&buffer[length], 0, padding);
feb11 3:85c6ee25cf3e 173 else
feb11 1:14a7cea431aa 174 {
feb11 3:85c6ee25cf3e 175 memset(&buffer[length], 0, 64-length);
feb11 3:85c6ee25cf3e 176 computeRounds(&a, &b, &c, &d, msg);
feb11 3:85c6ee25cf3e 177 memset(buffer, 0, length);
feb11 1:14a7cea431aa 178 }
feb11 3:85c6ee25cf3e 179
feb11 0:7a1237bd2d13 180 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 181 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 1:14a7cea431aa 182 memcpy(&buffer[56], &lengthBitLow, 4);
feb11 1:14a7cea431aa 183 memcpy(&buffer[60], &lengthBitHigh, 4);
feb11 0:7a1237bd2d13 184
feb11 1:14a7cea431aa 185 computeRounds(&a, &b, &c, &d, buffer);
feb11 1:14a7cea431aa 186
feb11 0:7a1237bd2d13 187 memcpy(digest, &a, 4);
feb11 0:7a1237bd2d13 188 memcpy(&digest[4], &b, 4);
feb11 0:7a1237bd2d13 189 memcpy(&digest[8], &c, 4);
feb11 0:7a1237bd2d13 190 memcpy(&digest[12], &d, 4);
feb11 0:7a1237bd2d13 191 }