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 11:14:51 2014 +0000
Revision:
13:ac8e23b98dae
Parent:
10:bc9c23aa3870
fixed warnings + fixed errors if compiling with gcc arm compiler

Who changed what in which revision?

UserRevisionLine numberNew contents of line
feb11 4:0da19393bd57 1 /**
feb11 4:0da19393bd57 2 Implementation of SHA-1 as described here:
feb11 4:0da19393bd57 3 http://tools.ietf.org/html/rfc1319
feb11 4:0da19393bd57 4 */
feb11 4:0da19393bd57 5
feb11 0:7a1237bd2d13 6 #include "SHA1.h"
feb11 0:7a1237bd2d13 7 #include <string.h>
feb11 0:7a1237bd2d13 8
feb11 3:85c6ee25cf3e 9 #define F0(B,C,D) ((B & C) | ((~B) & D))
feb11 3:85c6ee25cf3e 10 #define F1(B,C,D) (B ^ C ^ D)
feb11 3:85c6ee25cf3e 11 #define F2(B,C,D) ((B & C) | (B & D) | (C & D))
feb11 3:85c6ee25cf3e 12 #define ROTL(W,N) (((W) << N) | ((W) >> (32-N)))
feb11 3:85c6ee25cf3e 13
feb11 10:bc9c23aa3870 14 #define K0 0x5A827999
feb11 10:bc9c23aa3870 15 #define K1 0x6ED9EBA1
feb11 10:bc9c23aa3870 16 #define K2 0x8F1BBCDC
feb11 10:bc9c23aa3870 17 #define K3 0xCA62C1D6
feb11 0:7a1237bd2d13 18
feb11 0:7a1237bd2d13 19
feb11 10:bc9c23aa3870 20 #define H0 0x67452301
feb11 10:bc9c23aa3870 21 #define H1 0xEFCDAB89
feb11 10:bc9c23aa3870 22 #define H2 0x98BADCFE
feb11 10:bc9c23aa3870 23 #define H3 0x10325476
feb11 10:bc9c23aa3870 24 #define H4 0xC3D2E1F0
feb11 3:85c6ee25cf3e 25
feb11 10:bc9c23aa3870 26 #define MASK 0xF
feb11 3:85c6ee25cf3e 27
feb11 3:85c6ee25cf3e 28 #define W(s) ( w[s] = ROTL(w[((s) + 13) & MASK] ^ w[((s) + 8) & MASK] ^ w[((s) + 2) & MASK] ^ w[s],1))
feb11 0:7a1237bd2d13 29
feb11 3:85c6ee25cf3e 30 #define R0(A,B,C,D,E,T) E += ROTL(A, 5) + F0(B, C, D) + w[T] + K0; \
feb11 3:85c6ee25cf3e 31 B = ROTL(B,30);
feb11 3:85c6ee25cf3e 32 #define R1(A,B,C,D,E,T) E += ROTL(A, 5) + F0(B, C, D) + W(T & MASK) + K0; \
feb11 3:85c6ee25cf3e 33 B = ROTL(B,30);
feb11 3:85c6ee25cf3e 34 #define R2(A,B,C,D,E,T) E += ROTL(A, 5) + F1(B, C, D) + W(T & MASK) + K1; \
feb11 3:85c6ee25cf3e 35 B = ROTL(B,30);
feb11 3:85c6ee25cf3e 36 #define R3(A,B,C,D,E,T) E += ROTL(A, 5) + F2(B, C, D) + W(T & MASK) + K2; \
feb11 3:85c6ee25cf3e 37 B = ROTL(B,30);
feb11 3:85c6ee25cf3e 38 #define R4(A,B,C,D,E,T) E += ROTL(A, 5) + F1(B, C, D) + W(T & MASK) + K3; \
feb11 3:85c6ee25cf3e 39 B = ROTL(B,30);
feb11 0:7a1237bd2d13 40
feb11 13:ac8e23b98dae 41
feb11 13:ac8e23b98dae 42 static uint32_t revWord(const uint32_t w)
feb11 13:ac8e23b98dae 43 {
feb11 13:ac8e23b98dae 44 #ifdef __CC_ARM
feb11 13:ac8e23b98dae 45 return __rev(w);
feb11 13:ac8e23b98dae 46 #else
feb11 13:ac8e23b98dae 47 return (w >> 24)
feb11 13:ac8e23b98dae 48 | ((w & 0x00FF0000) >> 8)
feb11 13:ac8e23b98dae 49 | ((w & 0x0000FF00) << 8)
feb11 13:ac8e23b98dae 50 | ((w & 0x000000FF) << 24);
feb11 13:ac8e23b98dae 51 #endif
feb11 13:ac8e23b98dae 52 }
feb11 3:85c6ee25cf3e 53
feb11 0:7a1237bd2d13 54 SHA1::SHA1():
feb11 0:7a1237bd2d13 55 HashAlgorithm(),
feb11 0:7a1237bd2d13 56 h0(H0),
feb11 0:7a1237bd2d13 57 h1(H1),
feb11 0:7a1237bd2d13 58 h2(H2),
feb11 0:7a1237bd2d13 59 h3(H3),
feb11 0:7a1237bd2d13 60 h4(H4),
feb11 0:7a1237bd2d13 61 totalBufferLength(0),
feb11 0:7a1237bd2d13 62 buffer(),
feb11 0:7a1237bd2d13 63 bufferLength(0)
feb11 0:7a1237bd2d13 64 {
feb11 0:7a1237bd2d13 65 }
feb11 0:7a1237bd2d13 66
feb11 0:7a1237bd2d13 67 uint8_t SHA1::outputSize() const
feb11 0:7a1237bd2d13 68 {
feb11 0:7a1237bd2d13 69 return 20;
feb11 0:7a1237bd2d13 70 }
feb11 0:7a1237bd2d13 71
feb11 6:19aa835f2bbb 72 void SHA1::update(uint8_t *data, uint32_t length)
feb11 0:7a1237bd2d13 73 {
feb11 13:ac8e23b98dae 74 if((int)length < 64-bufferLength)
feb11 0:7a1237bd2d13 75 {
feb11 6:19aa835f2bbb 76 memcpy(&buffer[bufferLength], data, length);
feb11 0:7a1237bd2d13 77 bufferLength += length;
feb11 0:7a1237bd2d13 78 totalBufferLength += length;
feb11 0:7a1237bd2d13 79 return;
feb11 0:7a1237bd2d13 80 }
feb11 0:7a1237bd2d13 81 int offset = 64-bufferLength;
feb11 6:19aa835f2bbb 82 memcpy(&buffer[bufferLength], data, offset);
feb11 0:7a1237bd2d13 83 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 0:7a1237bd2d13 84 while(length-offset > 64)
feb11 0:7a1237bd2d13 85 {
feb11 6:19aa835f2bbb 86 memcpy(buffer, &data[offset], 64);
feb11 0:7a1237bd2d13 87 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 0:7a1237bd2d13 88 offset += 64;
feb11 0:7a1237bd2d13 89 }
feb11 13:ac8e23b98dae 90 if(offset > (int)length)
feb11 0:7a1237bd2d13 91 offset -= 64;
feb11 0:7a1237bd2d13 92 bufferLength = length - offset;
feb11 6:19aa835f2bbb 93 memcpy(buffer, &data[offset], bufferLength);
feb11 0:7a1237bd2d13 94 totalBufferLength += length;
feb11 0:7a1237bd2d13 95 }
feb11 0:7a1237bd2d13 96
feb11 6:19aa835f2bbb 97 void SHA1::finalize(uint8_t *hash)
feb11 0:7a1237bd2d13 98 {
feb11 6:19aa835f2bbb 99 uint32_t *hash2 = (uint32_t*)hash;
feb11 0:7a1237bd2d13 100 uint16_t padding;
feb11 0:7a1237bd2d13 101 if(totalBufferLength % 64 < 56)
feb11 0:7a1237bd2d13 102 padding = 56 - (totalBufferLength % 64);
feb11 0:7a1237bd2d13 103 else
feb11 0:7a1237bd2d13 104 padding = 56 + (64 - (totalBufferLength % 64));
feb11 3:85c6ee25cf3e 105
feb11 3:85c6ee25cf3e 106 buffer[bufferLength++] = 0x80;
feb11 3:85c6ee25cf3e 107 padding--;
feb11 3:85c6ee25cf3e 108 if(padding+bufferLength == 56)
feb11 3:85c6ee25cf3e 109 memset(&buffer[bufferLength], 0, padding);
feb11 3:85c6ee25cf3e 110 else
feb11 3:85c6ee25cf3e 111 {
feb11 3:85c6ee25cf3e 112 memset(&buffer[bufferLength], 0, 64-bufferLength);
feb11 3:85c6ee25cf3e 113 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 5:06cd9c8afa0b 114 memset(buffer, 0, 56);
feb11 3:85c6ee25cf3e 115 }
feb11 3:85c6ee25cf3e 116
feb11 3:85c6ee25cf3e 117 uint64_t lengthBit = totalBufferLength << 3;
feb11 0:7a1237bd2d13 118 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 119 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 13:ac8e23b98dae 120 lengthBitLow = revWord(lengthBitLow);
feb11 13:ac8e23b98dae 121 lengthBitHigh = revWord(lengthBitHigh);
feb11 3:85c6ee25cf3e 122 memcpy(&buffer[56], &lengthBitHigh, 4);
feb11 3:85c6ee25cf3e 123 memcpy(&buffer[60], &lengthBitLow, 4);
feb11 3:85c6ee25cf3e 124 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 3:85c6ee25cf3e 125
feb11 13:ac8e23b98dae 126 hash2[0] = revWord(h0);
feb11 13:ac8e23b98dae 127 hash2[1] = revWord(h1);
feb11 13:ac8e23b98dae 128 hash2[2] = revWord(h2);
feb11 13:ac8e23b98dae 129 hash2[3] = revWord(h3);
feb11 13:ac8e23b98dae 130 hash2[4] = revWord(h4);
feb11 0:7a1237bd2d13 131
feb11 0:7a1237bd2d13 132 // reset state
feb11 0:7a1237bd2d13 133 h0 = H0;
feb11 0:7a1237bd2d13 134 h1 = H1;
feb11 0:7a1237bd2d13 135 h2 = H2;
feb11 0:7a1237bd2d13 136 h3 = H3;
feb11 0:7a1237bd2d13 137 h4 = H4;
feb11 0:7a1237bd2d13 138 totalBufferLength = 0;
feb11 0:7a1237bd2d13 139 bufferLength = 0;
feb11 0:7a1237bd2d13 140 }
feb11 0:7a1237bd2d13 141
feb11 6:19aa835f2bbb 142
feb11 6:19aa835f2bbb 143 void SHA1::computeHash(uint8_t *hash, uint8_t *data, uint32_t length)
feb11 6:19aa835f2bbb 144 {
feb11 6:19aa835f2bbb 145 uint32_t *hash2 = (uint32_t*)hash;
feb11 6:19aa835f2bbb 146 uint64_t lengthBit = length << 3;
feb11 6:19aa835f2bbb 147 uint32_t padding;
feb11 6:19aa835f2bbb 148 if(length % 64 < 56)
feb11 6:19aa835f2bbb 149 padding = 56 - (length % 64);
feb11 6:19aa835f2bbb 150 else
feb11 6:19aa835f2bbb 151 padding = 56 + (64 - (length % 64));
feb11 6:19aa835f2bbb 152
feb11 6:19aa835f2bbb 153 uint32_t h0 = H0, h1 = H1, h2 = H2, h3 = H3, h4 = H4;
feb11 6:19aa835f2bbb 154 while(length >= 64)
feb11 6:19aa835f2bbb 155 {
feb11 6:19aa835f2bbb 156 computeBlock(&h0,&h1,&h2,&h3,&h4, data);
feb11 6:19aa835f2bbb 157 length -= 64;
feb11 6:19aa835f2bbb 158 data += 64;
feb11 6:19aa835f2bbb 159 }
feb11 6:19aa835f2bbb 160
feb11 6:19aa835f2bbb 161 uint8_t buffer[64];
feb11 6:19aa835f2bbb 162 memcpy(buffer, data, length);
feb11 6:19aa835f2bbb 163 buffer[length++] = 0x80;
feb11 6:19aa835f2bbb 164 padding--;
feb11 6:19aa835f2bbb 165 if(padding+length+8 == 64)
feb11 6:19aa835f2bbb 166 memset(&buffer[length], 0, padding);
feb11 6:19aa835f2bbb 167 else
feb11 6:19aa835f2bbb 168 {
feb11 6:19aa835f2bbb 169 memset(&buffer[length], 0, 64-length);
feb11 6:19aa835f2bbb 170 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 6:19aa835f2bbb 171 memset(buffer, 0, 56);
feb11 6:19aa835f2bbb 172 }
feb11 6:19aa835f2bbb 173
feb11 6:19aa835f2bbb 174 uint32_t lengthBitLow = lengthBit;
feb11 6:19aa835f2bbb 175 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 13:ac8e23b98dae 176 lengthBitLow = revWord(lengthBitLow);
feb11 13:ac8e23b98dae 177 lengthBitHigh = revWord(lengthBitHigh);
feb11 6:19aa835f2bbb 178 memcpy(&buffer[60], &lengthBitLow, 4);
feb11 6:19aa835f2bbb 179 memcpy(&buffer[56], &lengthBitHigh, 4);
feb11 6:19aa835f2bbb 180
feb11 6:19aa835f2bbb 181 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 6:19aa835f2bbb 182
feb11 13:ac8e23b98dae 183 hash2[0] = revWord(h0);
feb11 13:ac8e23b98dae 184 hash2[1] = revWord(h1);
feb11 13:ac8e23b98dae 185 hash2[2] = revWord(h2);
feb11 13:ac8e23b98dae 186 hash2[3] = revWord(h3);
feb11 13:ac8e23b98dae 187 hash2[4] = revWord(h4);
feb11 6:19aa835f2bbb 188 }
feb11 6:19aa835f2bbb 189
feb11 0:7a1237bd2d13 190 void SHA1::computeBlock(uint32_t *h02, uint32_t *h12, uint32_t *h22, uint32_t *h32, uint32_t *h42, uint8_t *buffer)
feb11 0:7a1237bd2d13 191 {
feb11 3:85c6ee25cf3e 192 uint32_t *buffer2 = (uint32_t*)buffer;
feb11 0:7a1237bd2d13 193 uint32_t w[16];
feb11 10:bc9c23aa3870 194
feb11 3:85c6ee25cf3e 195 for(int t = 0; t < 16; ++t)
feb11 13:ac8e23b98dae 196 w[t] = revWord(buffer2[t]);
feb11 0:7a1237bd2d13 197
feb11 0:7a1237bd2d13 198 uint32_t a = *h02, b = *h12, c = *h22, d = *h32, e = *h42;
feb11 3:85c6ee25cf3e 199
feb11 3:85c6ee25cf3e 200 R0(a,b,c,d,e, 0) R0(e,a,b,c,d, 1) R0(d,e,a,b,c, 2) R0(c,d,e,a,b, 3)
feb11 3:85c6ee25cf3e 201 R0(b,c,d,e,a, 4) R0(a,b,c,d,e, 5) R0(e,a,b,c,d, 6) R0(d,e,a,b,c, 7)
feb11 3:85c6ee25cf3e 202 R0(c,d,e,a,b, 8) R0(b,c,d,e,a, 9) R0(a,b,c,d,e,10) R0(e,a,b,c,d,11)
feb11 3:85c6ee25cf3e 203 R0(d,e,a,b,c,12) R0(c,d,e,a,b,13) R0(b,c,d,e,a,14) R0(a,b,c,d,e,15)
feb11 3:85c6ee25cf3e 204 R1(e,a,b,c,d,16) R1(d,e,a,b,c,17) R1(c,d,e,a,b,18) R1(b,c,d,e,a,19)
feb11 3:85c6ee25cf3e 205
feb11 3:85c6ee25cf3e 206
feb11 3:85c6ee25cf3e 207 R2(a,b,c,d,e,20) R2(e,a,b,c,d,21) R2(d,e,a,b,c,22) R2(c,d,e,a,b,23)
feb11 3:85c6ee25cf3e 208 R2(b,c,d,e,a,24) R2(a,b,c,d,e,25) R2(e,a,b,c,d,26) R2(d,e,a,b,c,27)
feb11 3:85c6ee25cf3e 209 R2(c,d,e,a,b,28) R2(b,c,d,e,a,29) R2(a,b,c,d,e,30) R2(e,a,b,c,d,31)
feb11 3:85c6ee25cf3e 210 R2(d,e,a,b,c,32) R2(c,d,e,a,b,33) R2(b,c,d,e,a,34) R2(a,b,c,d,e,35)
feb11 3:85c6ee25cf3e 211 R2(e,a,b,c,d,36) R2(d,e,a,b,c,37) R2(c,d,e,a,b,38) R2(b,c,d,e,a,39)
feb11 3:85c6ee25cf3e 212
feb11 3:85c6ee25cf3e 213 R3(a,b,c,d,e,40) R3(e,a,b,c,d,41) R3(d,e,a,b,c,42) R3(c,d,e,a,b,43)
feb11 3:85c6ee25cf3e 214 R3(b,c,d,e,a,44) R3(a,b,c,d,e,45) R3(e,a,b,c,d,46) R3(d,e,a,b,c,47)
feb11 3:85c6ee25cf3e 215 R3(c,d,e,a,b,48) R3(b,c,d,e,a,49) R3(a,b,c,d,e,50) R3(e,a,b,c,d,51)
feb11 3:85c6ee25cf3e 216 R3(d,e,a,b,c,52) R3(c,d,e,a,b,53) R3(b,c,d,e,a,54) R3(a,b,c,d,e,55)
feb11 3:85c6ee25cf3e 217 R3(e,a,b,c,d,56) R3(d,e,a,b,c,57) R3(c,d,e,a,b,58) R3(b,c,d,e,a,59)
feb11 3:85c6ee25cf3e 218
feb11 3:85c6ee25cf3e 219
feb11 3:85c6ee25cf3e 220 R4(a,b,c,d,e,60) R4(e,a,b,c,d,61) R4(d,e,a,b,c,62) R4(c,d,e,a,b,63)
feb11 3:85c6ee25cf3e 221 R4(b,c,d,e,a,64) R4(a,b,c,d,e,65) R4(e,a,b,c,d,66) R4(d,e,a,b,c,67)
feb11 3:85c6ee25cf3e 222 R4(c,d,e,a,b,68) R4(b,c,d,e,a,69) R4(a,b,c,d,e,70) R4(e,a,b,c,d,71)
feb11 3:85c6ee25cf3e 223 R4(d,e,a,b,c,72) R4(c,d,e,a,b,73) R4(b,c,d,e,a,74) R4(a,b,c,d,e,75)
feb11 3:85c6ee25cf3e 224 R4(e,a,b,c,d,76) R4(d,e,a,b,c,77) R4(c,d,e,a,b,78) R4(b,c,d,e,a,79)
feb11 0:7a1237bd2d13 225
feb11 0:7a1237bd2d13 226 *h02 += a;
feb11 0:7a1237bd2d13 227 *h12 += b;
feb11 0:7a1237bd2d13 228 *h22 += c;
feb11 0:7a1237bd2d13 229 *h32 += d;
feb11 0:7a1237bd2d13 230 *h42 += e;
feb11 0:7a1237bd2d13 231 }