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 15:08:51 2013 +0000
Revision:
5:06cd9c8afa0b
Parent:
4:0da19393bd57
Child:
6:19aa835f2bbb
change API & small improvements in SHA-2

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 5:06cd9c8afa0b 62 void SHA1::update(uint8_t *in, uint32_t length)
feb11 0:7a1237bd2d13 63 {
feb11 0:7a1237bd2d13 64 if(length < 64-bufferLength)
feb11 0:7a1237bd2d13 65 {
feb11 0:7a1237bd2d13 66 memcpy(&buffer[bufferLength], in, 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 0:7a1237bd2d13 72 memcpy(&buffer[bufferLength], in, 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 0:7a1237bd2d13 76 memcpy(buffer, &in[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 0:7a1237bd2d13 83 memcpy(buffer, &in[offset], bufferLength);
feb11 0:7a1237bd2d13 84 totalBufferLength += length;
feb11 0:7a1237bd2d13 85 }
feb11 0:7a1237bd2d13 86
feb11 5:06cd9c8afa0b 87 void SHA1::finalize(uint8_t *digest)
feb11 0:7a1237bd2d13 88 {
feb11 3:85c6ee25cf3e 89 uint32_t *digest2 = (uint32_t*)digest;
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 3:85c6ee25cf3e 116 digest2[0] = __rev(h0);
feb11 3:85c6ee25cf3e 117 digest2[1] = __rev(h1);
feb11 3:85c6ee25cf3e 118 digest2[2] = __rev(h2);
feb11 3:85c6ee25cf3e 119 digest2[3] = __rev(h3);
feb11 3:85c6ee25cf3e 120 digest2[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 0:7a1237bd2d13 132 void SHA1::computeBlock(uint32_t *h02, uint32_t *h12, uint32_t *h22, uint32_t *h32, uint32_t *h42, uint8_t *buffer)
feb11 0:7a1237bd2d13 133 {
feb11 3:85c6ee25cf3e 134 uint32_t *buffer2 = (uint32_t*)buffer;
feb11 0:7a1237bd2d13 135 uint32_t w[16];
feb11 3:85c6ee25cf3e 136 for(int t = 0; t < 16; ++t)
feb11 3:85c6ee25cf3e 137 w[t] = __rev(buffer2[t]);
feb11 0:7a1237bd2d13 138
feb11 0:7a1237bd2d13 139 uint32_t a = *h02, b = *h12, c = *h22, d = *h32, e = *h42;
feb11 3:85c6ee25cf3e 140
feb11 3:85c6ee25cf3e 141 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 142 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 143 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 144 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 145 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 146
feb11 3:85c6ee25cf3e 147
feb11 3:85c6ee25cf3e 148 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 149 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 150 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 151 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 152 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 153
feb11 3:85c6ee25cf3e 154 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 155 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 156 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 157 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 158 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 159
feb11 3:85c6ee25cf3e 160
feb11 3:85c6ee25cf3e 161 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 162 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 163 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 164 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 165 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 166
feb11 0:7a1237bd2d13 167 *h02 += a;
feb11 0:7a1237bd2d13 168 *h12 += b;
feb11 0:7a1237bd2d13 169 *h22 += c;
feb11 0:7a1237bd2d13 170 *h32 += d;
feb11 0:7a1237bd2d13 171 *h42 += e;
feb11 0:7a1237bd2d13 172 }
feb11 0:7a1237bd2d13 173
feb11 0:7a1237bd2d13 174
feb11 0:7a1237bd2d13 175
feb11 3:85c6ee25cf3e 176 /* method 1 */
feb11 0:7a1237bd2d13 177 void SHA1::computeDigest(uint8_t *digest, uint8_t *in, uint32_t length)
feb11 0:7a1237bd2d13 178 {
feb11 3:85c6ee25cf3e 179 uint64_t lengthBit = length << 3;
feb11 3:85c6ee25cf3e 180 uint32_t padding;
feb11 0:7a1237bd2d13 181 if(length % 64 < 56)
feb11 0:7a1237bd2d13 182 padding = 56 - (length % 64);
feb11 0:7a1237bd2d13 183 else
feb11 0:7a1237bd2d13 184 padding = 56 + (64 - (length % 64));
feb11 1:14a7cea431aa 185
feb11 1:14a7cea431aa 186 uint32_t h0 = H0, h1 = H1, h2 = H2, h3 = H3, h4 = H4;
feb11 3:85c6ee25cf3e 187 while(length >= 64)
feb11 1:14a7cea431aa 188 {
feb11 3:85c6ee25cf3e 189 computeBlock(&h0,&h1,&h2,&h3,&h4, in);
feb11 3:85c6ee25cf3e 190 length -= 64;
feb11 3:85c6ee25cf3e 191 in += 64;
feb11 3:85c6ee25cf3e 192 }
feb11 3:85c6ee25cf3e 193
feb11 3:85c6ee25cf3e 194 uint8_t buffer[64];
feb11 3:85c6ee25cf3e 195 memcpy(buffer, in, length);
feb11 3:85c6ee25cf3e 196 buffer[length++] = 0x80;
feb11 3:85c6ee25cf3e 197 padding--;
feb11 3:85c6ee25cf3e 198 if(padding+length+8 == 64)
feb11 3:85c6ee25cf3e 199 memset(&buffer[length], 0, padding);
feb11 3:85c6ee25cf3e 200 else
feb11 3:85c6ee25cf3e 201 {
feb11 3:85c6ee25cf3e 202 memset(&buffer[length], 0, 64-length);
feb11 3:85c6ee25cf3e 203 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 5:06cd9c8afa0b 204 memset(buffer, 0, 56);
feb11 1:14a7cea431aa 205 }
feb11 1:14a7cea431aa 206
feb11 0:7a1237bd2d13 207 uint32_t lengthBitLow = lengthBit;
feb11 0:7a1237bd2d13 208 uint32_t lengthBitHigh = lengthBit >> 32;
feb11 2:473bac39ae7c 209 lengthBitLow = __rev(lengthBitLow);
feb11 2:473bac39ae7c 210 lengthBitHigh = __rev(lengthBitHigh);
feb11 2:473bac39ae7c 211 memcpy(&buffer[60], &lengthBitLow, 4);
feb11 2:473bac39ae7c 212 memcpy(&buffer[56], &lengthBitHigh, 4);
feb11 0:7a1237bd2d13 213
feb11 1:14a7cea431aa 214 computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
feb11 0:7a1237bd2d13 215
feb11 2:473bac39ae7c 216 h0 = __rev(h0);
feb11 2:473bac39ae7c 217 h1 = __rev(h1);
feb11 2:473bac39ae7c 218 h2 = __rev(h2);
feb11 2:473bac39ae7c 219 h3 = __rev(h3);
feb11 2:473bac39ae7c 220 h4 = __rev(h4);
feb11 2:473bac39ae7c 221
feb11 2:473bac39ae7c 222 memcpy(digest, &h0, 4);
feb11 2:473bac39ae7c 223 memcpy(&digest[4], &h1, 4);
feb11 2:473bac39ae7c 224 memcpy(&digest[8], &h2, 4);
feb11 2:473bac39ae7c 225 memcpy(&digest[12], &h3, 4);
feb11 2:473bac39ae7c 226 memcpy(&digest[16], &h4, 4);
feb11 0:7a1237bd2d13 227 }
feb11 0:7a1237bd2d13 228