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

Files at this revision

API Documentation at this revision

Comitter:
feb11
Date:
Sat Sep 14 20:54:59 2013 +0000
Parent:
7:2dbbdfb08123
Child:
9:e34e076fb223
Commit message:
refactored public API for ciphers & added TDES

Changed in this revision

Crypto.h Show annotated file Show diff for this revision Revisions of this file
cipher/AES.cpp Show annotated file Show diff for this revision Revisions of this file
cipher/AES.h Show annotated file Show diff for this revision Revisions of this file
cipher/BlockCipher.cpp Show annotated file Show diff for this revision Revisions of this file
cipher/BlockCipher.h Show annotated file Show diff for this revision Revisions of this file
cipher/Cipher.cpp Show annotated file Show diff for this revision Revisions of this file
cipher/Cipher.h Show annotated file Show diff for this revision Revisions of this file
cipher/DES.cpp Show annotated file Show diff for this revision Revisions of this file
cipher/DES.h Show annotated file Show diff for this revision Revisions of this file
cipher/RC4.cpp Show annotated file Show diff for this revision Revisions of this file
cipher/RC4.h Show annotated file Show diff for this revision Revisions of this file
cipher/StreamCipher.cpp Show annotated file Show diff for this revision Revisions of this file
cipher/StreamCipher.h Show annotated file Show diff for this revision Revisions of this file
cipher/TDES.cpp Show annotated file Show diff for this revision Revisions of this file
cipher/TDES.h Show annotated file Show diff for this revision Revisions of this file
--- a/Crypto.h	Sat Sep 14 18:21:32 2013 +0000
+++ b/Crypto.h	Sat Sep 14 20:54:59 2013 +0000
@@ -3,6 +3,8 @@
 
 #include "AES.h"
 #include "RC4.h"
+#include "DES.h"
+#include "TDES.h"
 
 #include "MD2.h"
 #include "MD5.h"
--- a/cipher/AES.cpp	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/AES.cpp	Sat Sep 14 20:54:59 2013 +0000
@@ -52,6 +52,32 @@
 };
 
 AES::AES(const AES_TYPE t, uint8_t *key):
+BlockCipher(16,ECB_MODE),
+state()
+{
+    switch(t)
+    {
+        case AES_128:
+            nr = 10;
+            nk = 4;
+        break;
+        
+        case AES_192:
+            nr = 12;
+            nk = 6;
+        break;
+        
+        case AES_256:
+            nr = 14;
+            nk = 8;
+        break;
+    }
+    
+    keyExpansion(key);
+}
+
+AES::AES(const AES_TYPE t, uint8_t *key, uint8_t *iv):
+BlockCipher(16,CBC_MODE, iv),
 state()
 {
     switch(t)
@@ -275,20 +301,3 @@
     
     memcpy(out, state, 16);
 }
-
-void AES::encrypt(uint8_t *out, uint8_t *in, uint32_t length)
-{
-    for(uint32_t i = 0; i < length; i+=16)
-        encryptBlock(&out[i], &in[i]);
-}
-
-void AES::decrypt(uint8_t *out, uint8_t *in, uint32_t length)
-{
-    for(uint32_t i = 0; i < length; i+=16)
-        decryptBlock(&out[i], &in[i]);
-}
-
-uint32_t AES::getBlockSize() const
-{
-    return 16;
-}
--- a/cipher/AES.h	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/AES.h	Sat Sep 14 20:54:59 2013 +0000
@@ -1,7 +1,7 @@
 #ifndef AES_H
 #define AES_H
 
-#include "Cipher.h"
+#include "BlockCipher.h"
 
 enum AES_TYPE
 {
@@ -10,20 +10,17 @@
     AES_256 = 8
 };
 
-class AES : public Cipher
+class AES : public BlockCipher
 {
     public :
     
         AES(const AES_TYPE type, uint8_t *key);
-        
-        virtual void encrypt(uint8_t *out, uint8_t *in, uint32_t length);
-        virtual void decrypt(uint8_t *out, uint8_t *in, uint32_t length);
-        virtual uint32_t getBlockSize() const;
-        
+        AES(const AES_TYPE type, uint8_t *key, uint8_t *iv);
+                
     private :
     
-        void encryptBlock(uint8_t *out, uint8_t *in);
-        void decryptBlock(uint8_t *out, uint8_t *in);
+        virtual void encryptBlock(uint8_t *out, uint8_t *in);
+        virtual void decryptBlock(uint8_t *out, uint8_t *in);
         
         void keyExpansion(uint8_t *key);
         uint32_t rotWord(uint32_t w);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cipher/BlockCipher.cpp	Sat Sep 14 20:54:59 2013 +0000
@@ -0,0 +1,50 @@
+#include "BlockCipher.h"
+#include <string.h>
+
+BlockCipher::BlockCipher(uint32_t bs, BLOCK_CIPHER_MODE m, uint8_t *iv):
+Cipher(),
+blockSize(bs),
+mode(m),
+IV(0)
+{
+    if(mode == CBC_MODE)
+    {
+        IV = new uint8_t[blockSize];
+        memcpy(IV, iv, blockSize); 
+    }
+}
+
+BlockCipher::~BlockCipher()
+{
+    if(IV != 0)
+        delete[] IV;
+}
+
+CIPHER_TYPE BlockCipher::getType() const
+{
+    return BLOCK_CIPHER;
+}
+
+uint32_t BlockCipher::getBlockSize() const
+{
+    return blockSize;
+}
+
+void BlockCipher::encrypt(uint8_t *out, uint8_t *in, uint32_t length)
+{
+    for(uint32_t i = 0; i < length; i += getBlockSize())
+    {
+        encryptBlock(&out[i], &in[i]);
+        
+    }
+}
+
+void BlockCipher::decrypt(uint8_t *out, uint8_t *in, uint32_t length)
+{
+    for(uint32_t i = 0; i < length; i += getBlockSize())
+    {
+        decryptBlock(&out[i], &in[i]);
+        
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cipher/BlockCipher.h	Sat Sep 14 20:54:59 2013 +0000
@@ -0,0 +1,37 @@
+#ifndef BLOCK_CIPHER_H
+#define BLOCK_CIPHER_H
+
+#include "Cipher.h"
+
+enum BLOCK_CIPHER_MODE
+{
+    ECB_MODE,
+    CBC_MODE
+};
+
+class BlockCipher : public Cipher
+{
+    public :
+    
+        BlockCipher(uint32_t bs, BLOCK_CIPHER_MODE m, uint8_t *iv = 0);
+        virtual ~BlockCipher();
+        
+        virtual CIPHER_TYPE getType() const;        
+        uint32_t getBlockSize() const;
+
+        virtual void encrypt(uint8_t *out, uint8_t *in, uint32_t length);        
+        virtual void decrypt(uint8_t *out, uint8_t *in, uint32_t length);        
+
+    protected :
+    
+        virtual void encryptBlock(uint8_t *out, uint8_t *in) = 0;
+        virtual void decryptBlock(uint8_t *out, uint8_t *in) = 0;
+
+    private :
+    
+        uint32_t blockSize;
+        BLOCK_CIPHER_MODE mode;
+        uint8_t *IV;
+};
+
+#endif
--- a/cipher/Cipher.cpp	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/Cipher.cpp	Sat Sep 14 20:54:59 2013 +0000
@@ -4,9 +4,3 @@
 {
 }
 
-
-CIPHER_TYPE Cipher::getType() const
-{
-    return getBlockSize() <= 1 ? STREAM_CIPHER : BLOCK_CIPHER;
-}
-
--- a/cipher/Cipher.h	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/Cipher.h	Sat Sep 14 20:54:59 2013 +0000
@@ -17,9 +17,8 @@
         
         virtual void encrypt(uint8_t *out, uint8_t *in, uint32_t length) = 0;        
         virtual void decrypt(uint8_t *out, uint8_t *in, uint32_t length) = 0;        
-        virtual uint32_t getBlockSize() const = 0;
 
-        CIPHER_TYPE getType() const;
+        virtual CIPHER_TYPE getType() const = 0;
 
 };
 
--- a/cipher/DES.cpp	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/DES.cpp	Sat Sep 14 20:54:59 2013 +0000
@@ -1,6 +1,4 @@
 #include "DES.h"
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 
 
@@ -215,21 +213,17 @@
 
 
 DES::DES(uint8_t *key):
-Cipher()
+BlockCipher(8,ECB_MODE)
 {
     generateSubKeys(key);
 }
 
-uint32_t DES::getBlockSize() const
+DES::DES(uint8_t *key, uint8_t *iv):
+BlockCipher(8,CBC_MODE, iv)
 {
-    return 8;
+    generateSubKeys(key);
 }
 
-CIPHER_TYPE DES::getType() const
-{
-    return BLOCK_CIPHER;
-};
-
 void DES::generateSubKeys(uint8_t *key)
 {
 
@@ -248,7 +242,7 @@
     }   
 }
 
-void DES::encrypt(uint8_t *out, uint8_t *in, uint32_t length)
+void DES::encryptBlock(uint8_t *out, uint8_t *in)
 {
     uint8_t tmp[8];
     memcpy(tmp, in, 8);
@@ -289,7 +283,7 @@
 }
 
 
-void DES::decrypt(uint8_t *out, uint8_t *in, uint32_t length)
+void DES::decryptBlock(uint8_t *out, uint8_t *in)
 {
     uint8_t tmp[8];
     memcpy(tmp, in, 8);
--- a/cipher/DES.h	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/DES.h	Sat Sep 14 20:54:59 2013 +0000
@@ -1,23 +1,23 @@
 #ifndef DES_H
 #define DES_H
 
-#include "Cipher.h"
+#include "BlockCipher.h"
 
+class TDES;
 
-class DES : public Cipher
+class DES : public BlockCipher
 {
+    friend class TDES;
+    
     public :
     
         DES(uint8_t* key);
-        
-        virtual void encrypt(uint8_t *out, uint8_t *in, uint32_t length);        
-        virtual void decrypt(uint8_t *out, uint8_t *in, uint32_t length);        
-        virtual uint32_t getBlockSize() const;
-
-        CIPHER_TYPE getType() const;
-        
+        DES(uint8_t *key, uint8_t *iv);
+                
     private :
     
+        virtual void encryptBlock(uint8_t *out, uint8_t *in);        
+        virtual void decryptBlock(uint8_t *out, uint8_t *in);    
         void generateSubKeys(uint8_t *key);
     
         uint8_t subKeys[16][7];
--- a/cipher/RC4.cpp	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/RC4.cpp	Sat Sep 14 20:54:59 2013 +0000
@@ -1,7 +1,7 @@
 #include "RC4.h"
 
 RC4::RC4(uint8_t *key, uint8_t keyLength):
-Cipher(),
+StreamCipher(),
 s(),
 i(0),
 j(0)
@@ -18,7 +18,7 @@
     } 
 }
 
-uint8_t RC4::encyptByte(uint8_t in)
+uint8_t RC4::encryptByte(uint8_t in)
 {
     ++i;
     j += s[i];
@@ -26,21 +26,10 @@
     s[i] = s[j];
     s[j] = tmp;
     uint8_t c = s[(s[i]+s[j])%256];
-    return in^c;
-}
-
-void RC4::encrypt(uint8_t *out, uint8_t *in, uint32_t length)
-{
-    for(uint32_t l = 0; l < length; ++l)
-        out[l] = encyptByte(in[l]);
+    return in^c;  
 }
 
-void RC4::decrypt(uint8_t *out, uint8_t *in, uint32_t length)    
+uint8_t RC4::decryptByte(uint8_t in)
 {
-    encrypt(out, in, length);
+    return encryptByte(in);
 }
-
-uint32_t RC4::getBlockSize() const
-{
-    return 1;
-}
--- a/cipher/RC4.h	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/RC4.h	Sat Sep 14 20:54:59 2013 +0000
@@ -1,22 +1,19 @@
 #ifndef RC4_H
 #define RC4_H
 
-#include "Cipher.h"
+#include "StreamCipher.h"
 
-class RC4 : public Cipher
+class RC4 : public StreamCipher
 {
     public :
     
         RC4(uint8_t *key, uint8_t keyLength);
         
-        virtual void encrypt(uint8_t *out, uint8_t *in, uint32_t length);        
-        virtual void decrypt(uint8_t *out, uint8_t *in, uint32_t length);        
-        virtual uint32_t getBlockSize() const;
-        
     private :
     
-        uint8_t encyptByte(uint8_t in);
-        
+        virtual uint8_t encryptByte(uint8_t in);
+        virtual uint8_t decryptByte(uint8_t in);
+                
         uint8_t s[256];
         uint8_t i,j;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cipher/StreamCipher.cpp	Sat Sep 14 20:54:59 2013 +0000
@@ -0,0 +1,23 @@
+#include "StreamCipher.h"
+
+
+StreamCipher::StreamCipher()
+{
+}
+
+CIPHER_TYPE StreamCipher::getType() const
+{
+    return STREAM_CIPHER;
+}
+
+void StreamCipher::encrypt(uint8_t *out, uint8_t *in, uint32_t length)
+{
+    for(uint32_t i = 0; i < length; ++i)
+        out[i] = encryptByte(in[i]);
+}
+        
+void StreamCipher::decrypt(uint8_t *out, uint8_t *in, uint32_t length) 
+{
+    for(uint32_t i = 0; i < length; ++i)
+        out[i] = decryptByte(in[i]);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cipher/StreamCipher.h	Sat Sep 14 20:54:59 2013 +0000
@@ -0,0 +1,24 @@
+#ifndef STREAM_CIPHER_H
+#define STREAM_CIPHER_H
+
+#include "Cipher.h"
+
+class StreamCipher : public Cipher
+{
+    public :
+    
+        StreamCipher();
+        
+        virtual CIPHER_TYPE getType() const;        
+
+        virtual void encrypt(uint8_t *out, uint8_t *in, uint32_t length);        
+        virtual void decrypt(uint8_t *out, uint8_t *in, uint32_t length);        
+
+    protected :
+    
+        virtual uint8_t encryptByte(uint8_t in) = 0;
+        virtual uint8_t decryptByte(uint8_t in) = 0;
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cipher/TDES.cpp	Sat Sep 14 20:54:59 2013 +0000
@@ -0,0 +1,35 @@
+#include "TDES.h"
+
+TDES::TDES(uint8_t *key1, uint8_t *key2, uint8_t *key3):
+BlockCipher(8,ECB_MODE),
+a(key1),
+b(key2),
+c(key3)
+{
+
+}
+
+TDES::TDES(uint8_t *key1, uint8_t *key2, uint8_t *key3, uint8_t *iv):
+BlockCipher(8,CBC_MODE,iv),
+a(key1),
+b(key2),
+c(key3)
+{
+
+}
+
+void TDES::encryptBlock(uint8_t *out, uint8_t *in)
+{
+    uint8_t tmp[8], tmp2[8];
+    a.encryptBlock(tmp,in);
+    b.decryptBlock(tmp2,tmp);
+    c.encryptBlock(out, tmp2);
+}
+
+void TDES::decryptBlock(uint8_t *out, uint8_t *in)
+{
+    uint8_t tmp[8], tmp2[8];
+    c.decryptBlock(tmp, in);
+    b.encryptBlock(tmp2, tmp);
+    a.decryptBlock(out, tmp2);
+}
--- a/cipher/TDES.h	Sat Sep 14 18:21:32 2013 +0000
+++ b/cipher/TDES.h	Sat Sep 14 20:54:59 2013 +0000
@@ -1,4 +1,22 @@
 #ifndef TDES_H
 #define TDES_H
 
+#include "DES.h"
+
+class TDES : public BlockCipher
+{
+    public :
+    
+        TDES(uint8_t *key1, uint8_t *key2, uint8_t *key3);
+        TDES(uint8_t *key1, uint8_t *key2, uint8_t *key3, uint8_t *iv);
+            
+    private :
+        
+        virtual void encryptBlock(uint8_t *out, uint8_t *in);        
+        virtual void decryptBlock(uint8_t *out, uint8_t *in);    
+    
+    
+        DES a,b,c;
+};
+
 #endif
\ No newline at end of file