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:
Tue Sep 24 07:19:04 2013 +0000
Revision:
10:bc9c23aa3870
Parent:
7:2dbbdfb08123
Child:
13:ac8e23b98dae
implemented HMAC

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 3:85c6ee25cf3e 41
feb11 0:7a1237bd2d13 42 SHA1::SHA1():
feb11 0:7a1237bd2d13 43 HashAlgorithm(),
feb11 0:7a1237bd2d13 44 h0(H0),
feb11 0:7a1237bd2d13 45 h1(H1),
feb11 0:7a1237bd2d13 46 h2(H2),
feb11 0:7a1237bd2d13 47 h3(H3),
feb11 0:7a1237bd2d13 48 h4(H4),
feb11 0:7a1237bd2d13 49 totalBufferLength(0),
feb11 0:7a1237bd2d13 50 buffer(),
feb11 0:7a1237bd2d13 51 bufferLength(0)
feb11 0:7a1237bd2d13 52 {
feb11 0:7a1237bd2d13 53 }
feb11 0:7a1237bd2d13 54
feb11 0:7a1237bd2d13 55 uint8_t SHA1::outputSize() const
feb11 0:7a1237bd2d13 56 {
feb11 0:7a1237bd2d13 57 return 20;
feb11 0:7a1237bd2d13 58 }
feb11 0:7a1237bd2d13 59
feb11 6:19aa835f2bbb 60 void SHA1::update(uint8_t *data, uint32_t length)
feb11 0:7a1237bd2d13 61 {
feb11 0:7a1237bd2d13 62 if(length < 64-bufferLength)
feb11 0:7a1237bd2d13 63 {
feb11 6:19aa835f2bbb 64 memcpy(&buffer[bufferLength], data, length);
feb11 0:7a1237bd2d13 65 bufferLength += length;
feb11 0:7a1237bd2d13 66 totalBufferLength += length;
feb11 0:7a1237bd2d13 67 return;
feb11 0:7a1237bd2d13 68 }
feb11 0:7a1237bd2d13 69 int offset = 64-bufferLength;
feb11 6:19aa835f2bbb 70 memcpy(&buffer[bufferLength], data, offset);
feb11 0:7a1237bd2d13 71 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 0:7a1237bd2d13 72 while(length-offset > 64)
feb11 0:7a1237bd2d13 73 {
feb11 6:19aa835f2bbb 74 memcpy(buffer, &data[offset], 64);
feb11 0:7a1237bd2d13 75 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 0:7a1237bd2d13 76 offset += 64;
feb11 0:7a1237bd2d13 77 }
feb11 0:7a1237bd2d13 78 if(offset > length)
feb11 0:7a1237bd2d13 79 offset -= 64;
feb11 0:7a1237bd2d13 80 bufferLength = length - offset;
feb11 6:19aa835f2bbb 81 memcpy(buffer, &data[offset], bufferLength);
feb11 0:7a1237bd2d13 82 totalBufferLength += length;
feb11 0:7a1237bd2d13 83 }
feb11 0:7a1237bd2d13 84
feb11 6:19aa835f2bbb 85 void SHA1::finalize(uint8_t *hash)
feb11 0:7a1237bd2d13 86 {
feb11 6:19aa835f2bbb 87 uint32_t *hash2 = (uint32_t*)hash;
feb11 0:7a1237bd2d13 88 uint16_t padding;
feb11 0:7a1237bd2d13 89 if(totalBufferLength % 64 < 56)
feb11 0:7a1237bd2d13 90 padding = 56 - (totalBufferLength % 64);
feb11 0:7a1237bd2d13 91 else
feb11 0:7a1237bd2d13 92 padding = 56 + (64 - (totalBufferLength % 64));
feb11 3:85c6ee25cf3e 93
feb11 3:85c6ee25cf3e 94 buffer[bufferLength++] = 0x80;
feb11 3:85c6ee25cf3e 95 padding--;
feb11 3:85c6ee25cf3e 96 if(padding+bufferLength == 56)
feb11 3:85c6ee25cf3e 97 memset(&buffer[bufferLength], 0, padding);
feb11 3:85c6ee25cf3e 98 else
feb11 3:85c6ee25cf3e 99 {
feb11 3:85c6ee25cf3e 100 memset(&buffer[bufferLength], 0, 64-bufferLength);
feb11 3:85c6ee25cf3e 101 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 5:06cd9c8afa0b 102 memset(buffer, 0, 56);
feb11 3:85c6ee25cf3e 103 }
feb11 3:85c6ee25cf3e 104
feb11 3:85c6ee25cf3e 105 uint64_t lengthBit = totalBufferLength << 3;
feb11 0:7a1237bd2d13 106 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 107 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 3:85c6ee25cf3e 108 lengthBitLow = __rev(lengthBitLow);
feb11 3:85c6ee25cf3e 109 lengthBitHigh = __rev(lengthBitHigh);
feb11 3:85c6ee25cf3e 110 memcpy(&buffer[56], &lengthBitHigh, 4);
feb11 3:85c6ee25cf3e 111 memcpy(&buffer[60], &lengthBitLow, 4);
feb11 3:85c6ee25cf3e 112 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 3:85c6ee25cf3e 113
feb11 6:19aa835f2bbb 114 hash2[0] = __rev(h0);
feb11 6:19aa835f2bbb 115 hash2[1] = __rev(h1);
feb11 6:19aa835f2bbb 116 hash2[2] = __rev(h2);
feb11 6:19aa835f2bbb 117 hash2[3] = __rev(h3);
feb11 6:19aa835f2bbb 118 hash2[4] = __rev(h4);
feb11 0:7a1237bd2d13 119
feb11 0:7a1237bd2d13 120 // reset state
feb11 0:7a1237bd2d13 121 h0 = H0;
feb11 0:7a1237bd2d13 122 h1 = H1;
feb11 0:7a1237bd2d13 123 h2 = H2;
feb11 0:7a1237bd2d13 124 h3 = H3;
feb11 0:7a1237bd2d13 125 h4 = H4;
feb11 0:7a1237bd2d13 126 totalBufferLength = 0;
feb11 0:7a1237bd2d13 127 bufferLength = 0;
feb11 0:7a1237bd2d13 128 }
feb11 0:7a1237bd2d13 129
feb11 6:19aa835f2bbb 130
feb11 6:19aa835f2bbb 131 void SHA1::computeHash(uint8_t *hash, uint8_t *data, uint32_t length)
feb11 6:19aa835f2bbb 132 {
feb11 6:19aa835f2bbb 133 uint32_t *hash2 = (uint32_t*)hash;
feb11 6:19aa835f2bbb 134 uint64_t lengthBit = length << 3;
feb11 6:19aa835f2bbb 135 uint32_t padding;
feb11 6:19aa835f2bbb 136 if(length % 64 < 56)
feb11 6:19aa835f2bbb 137 padding = 56 - (length % 64);
feb11 6:19aa835f2bbb 138 else
feb11 6:19aa835f2bbb 139 padding = 56 + (64 - (length % 64));
feb11 6:19aa835f2bbb 140
feb11 6:19aa835f2bbb 141 uint32_t h0 = H0, h1 = H1, h2 = H2, h3 = H3, h4 = H4;
feb11 6:19aa835f2bbb 142 while(length >= 64)
feb11 6:19aa835f2bbb 143 {
feb11 6:19aa835f2bbb 144 computeBlock(&h0,&h1,&h2,&h3,&h4, data);
feb11 6:19aa835f2bbb 145 length -= 64;
feb11 6:19aa835f2bbb 146 data += 64;
feb11 6:19aa835f2bbb 147 }
feb11 6:19aa835f2bbb 148
feb11 6:19aa835f2bbb 149 uint8_t buffer[64];
feb11 6:19aa835f2bbb 150 memcpy(buffer, data, length);
feb11 6:19aa835f2bbb 151 buffer[length++] = 0x80;
feb11 6:19aa835f2bbb 152 padding--;
feb11 6:19aa835f2bbb 153 if(padding+length+8 == 64)
feb11 6:19aa835f2bbb 154 memset(&buffer[length], 0, padding);
feb11 6:19aa835f2bbb 155 else
feb11 6:19aa835f2bbb 156 {
feb11 6:19aa835f2bbb 157 memset(&buffer[length], 0, 64-length);
feb11 6:19aa835f2bbb 158 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 6:19aa835f2bbb 159 memset(buffer, 0, 56);
feb11 6:19aa835f2bbb 160 }
feb11 6:19aa835f2bbb 161
feb11 6:19aa835f2bbb 162 uint32_t lengthBitLow = lengthBit;
feb11 6:19aa835f2bbb 163 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 6:19aa835f2bbb 164 lengthBitLow = __rev(lengthBitLow);
feb11 6:19aa835f2bbb 165 lengthBitHigh = __rev(lengthBitHigh);
feb11 6:19aa835f2bbb 166 memcpy(&buffer[60], &lengthBitLow, 4);
feb11 6:19aa835f2bbb 167 memcpy(&buffer[56], &lengthBitHigh, 4);
feb11 6:19aa835f2bbb 168
feb11 6:19aa835f2bbb 169 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 6:19aa835f2bbb 170
feb11 6:19aa835f2bbb 171 hash2[0] = __rev(h0);
feb11 6:19aa835f2bbb 172 hash2[1] = __rev(h1);
feb11 6:19aa835f2bbb 173 hash2[2] = __rev(h2);
feb11 6:19aa835f2bbb 174 hash2[3] = __rev(h3);
feb11 6:19aa835f2bbb 175 hash2[4] = __rev(h4);
feb11 6:19aa835f2bbb 176 }
feb11 6:19aa835f2bbb 177
feb11 0:7a1237bd2d13 178 void SHA1::computeBlock(uint32_t *h02, uint32_t *h12, uint32_t *h22, uint32_t *h32, uint32_t *h42, uint8_t *buffer)
feb11 0:7a1237bd2d13 179 {
feb11 3:85c6ee25cf3e 180 uint32_t *buffer2 = (uint32_t*)buffer;
feb11 0:7a1237bd2d13 181 uint32_t w[16];
feb11 10:bc9c23aa3870 182
feb11 3:85c6ee25cf3e 183 for(int t = 0; t < 16; ++t)
feb11 3:85c6ee25cf3e 184 w[t] = __rev(buffer2[t]);
feb11 0:7a1237bd2d13 185
feb11 0:7a1237bd2d13 186 uint32_t a = *h02, b = *h12, c = *h22, d = *h32, e = *h42;
feb11 3:85c6ee25cf3e 187
feb11 3:85c6ee25cf3e 188 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 189 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 190 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 191 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 192 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 193
feb11 3:85c6ee25cf3e 194
feb11 3:85c6ee25cf3e 195 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 196 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 197 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 198 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 199 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 200
feb11 3:85c6ee25cf3e 201 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 202 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 203 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 204 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 205 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 206
feb11 3:85c6ee25cf3e 207
feb11 3:85c6ee25cf3e 208 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 209 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 210 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 211 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 212 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 213
feb11 0:7a1237bd2d13 214 *h02 += a;
feb11 0:7a1237bd2d13 215 *h12 += b;
feb11 0:7a1237bd2d13 216 *h22 += c;
feb11 0:7a1237bd2d13 217 *h32 += d;
feb11 0:7a1237bd2d13 218 *h42 += e;
feb11 0:7a1237bd2d13 219 }
feb11 0:7a1237bd2d13 220