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