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:
Sat Sep 07 23:47:28 2013 +0000
Revision:
0:7a1237bd2d13
Child:
1:14a7cea431aa
initial import

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