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 16:03:43 2013 +0000
Revision:
6:19aa835f2bbb
Parent:
5:06cd9c8afa0b
change public API for hash + small improvements for hash + rearrange code

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