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:
Sun May 11 13:36:45 2014 +0000
Revision:
14:f04410cef037
Parent:
13:ac8e23b98dae
CBC mode completed

Who changed what in which revision?

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