Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I created a CRYPTOSOCKET class for encrypted comms. It also has a public "encrypt" and "decrypt" function. The socket part really just does encrypt/decrypt and calls send/recv for you. The "socket" functionality of it can be easily stripped out.</p> <p>This is C++. If you want C, just look at the encrypt and decrypt functions of the CRYPTOSOCKET class and the constructor. Its very simple. Also, this is HC-256, not HC-128.</p> <p>In a header "crypto.hpp".</p> <pre><code>#include "ecrypt-sync.h" #ifndef CRYPTO_H #define CRYPTO_H class CRYPTOSOCKET{ public: /** * Creates and initializes the structures required for encryption. * * @param[in] socket * The socket to send and receive data on. This should already be connected. * @param[in] key * The key used for encryption and decryption. * @param[in] iv * The initialization vector used by AES256 CBC mode. This can just be random bytes. * * @see generateRandom */ CRYPTOSOCKET(int socket, unsigned char *key, unsigned char *iv); ~CRYPTOSOCKET(); /** * A wrapper for sending data across the connection. * * This encrypts the data into an intermediate buffer * prior to sending it across the wire. * * @see man send */ ssize_t send(const void *buf, size_t len, int flags); /** * A wrapper for receiving data across the connection. * * This receives the encrypted data into an intermediate buffer, * then decrypts it, and writes it to the output buffer. * * @see man recv */ ssize_t recv(void *buf, size_t len, int flags); /** * Encrypts the specified data and places the encrypted data in the specified buffer. * * @param len Used as input for how long the plaintext is, then for output of how long the cipher text is. * @param[in] plaintext The unencrypted data to encrypt. * @param[out] ciphertext Where to place the encrypted data. * * @returns A pointer to the ciphertext. * * @see unsigned char *decrypt(unsigned char *ciphertext, unsigned int len, unsigned char *plaintext) */ unsigned char *encrypt(unsigned char *plaintext, unsigned int len, unsigned char *ciphertext); /** * Decrypts the specified data and places the unencrypted data into the specified buffer. * * @param len Used as input for how long the ciphertext is and as output for how long the plaintext is. * @param[in] ciphertext The encrypted data to unencrypt. * @param[out] plaintext The buffer to place the unencrypted data in. * * @returns A pointer to the plaintext. * * @see unsigned char *encrypt(unsigned char *plaintext, unsigned int len, unsigned char *ciphertext) */ unsigned char *decrypt(unsigned char *ciphertext, unsigned int len, unsigned char *plaintext); int sock; /**&lt; The underlying socket that this sends and receives on. */ private: ECRYPT_ctx e_ctx; /**&lt; The ctx used for encryption. */ ECRYPT_ctx d_ctx; /**&lt; The ctx used for decryption. */ }; #endif </code></pre> <p>And inside "crypto.cpp":</p> <pre><code>#include "crypto.hpp" #include &lt;sys/types.h&gt; #include &lt;sys/socket.h&gt; CRYPTOSOCKET::CRYPTOSOCKET(int socket, unsigned char *key, unsigned char *iv){ // Initialize the encryptor. ECRYPT_keysetup(&amp;e_ctx, key, 128, 128); ECRYPT_ivsetup(&amp;e_ctx, iv); // Initialize the decryptor. ECRYPT_keysetup(&amp;d_ctx, key, 128, 128); ECRYPT_ivsetup(&amp;d_ctx, iv); sock = socket; }; CRYPTOSOCKET::~CRYPTOSOCKET(){ // Nothing to do. }; unsigned char *CRYPTOSOCKET::encrypt(unsigned char *plaintext, unsigned int len, unsigned char *ciphertext){ ECRYPT_process_bytes(0, &amp;e_ctx, plaintext, ciphertext, len); return ciphertext; } unsigned char *CRYPTOSOCKET::decrypt(unsigned char *ciphertext, unsigned int len, unsigned char *plaintext){ ECRYPT_process_bytes(1, &amp;d_ctx, ciphertext, plaintext, len); return plaintext; } ssize_t CRYPTOSOCKET::send(const void *buf, size_t len, int flags){ unsigned char buffer[len]; encrypt((unsigned char*)buf, len, buffer); return ::send(sock, buffer, len, MSG_WAITALL); }; ssize_t CRYPTOSOCKET::recv(void *buf, size_t len, int flags){ unsigned char buffer[len]; int data = ::recv(sock, buffer, len, MSG_WAITALL); if(data &gt; 0) decrypt(buffer, len, (unsigned char *)buf); return data; }; /******************************************************************* * ECRYPT crap below here.... */ /* ecrypt-sync.c */ /* *** Please do not edit below here. *** */ //#include "ecrypt-sync.h" void ECRYPT_init(void){ }; void ECRYPT_process_bytes( int action, /* 0 = encrypt; 1 = decrypt; */ ECRYPT_ctx* ctx, const u8* input, u8* output, u32 msglen) /* Message length in bytes. */ { u32 i, j, msglen32, keystreamword; msglen32 = msglen &gt;&gt; 2; for (i = 0; i &lt; msglen32; i++) { keystreamword = generate(ctx); /*generate a 32-bit word*/ for (j = 0; j &lt; 4; j++) { *output = *input ^ keystreamword; /*encrypt one byte*/ output += 1; input +=1; keystreamword = keystreamword &gt;&gt; 8; } } keystreamword = generate(ctx); for (i = 0; i &lt; (msglen &amp; 3); i++) { *output = *input ^ keystreamword; /*encrypt one byte*/ output += 1; input +=1; keystreamword = keystreamword &gt;&gt; 8; } } void ECRYPT_ivsetup( ECRYPT_ctx* ctx, const u8* iv) { u32 W[2560],i; /* initialize the iv */ for (i = 0; i &lt; 8; i++) ctx-&gt;iv[i] = 0; for (i = 0; (i &lt; ctx-&gt;ivsize) &amp; (i &lt; 32); i++) { ctx-&gt;iv[i &gt;&gt; 2] = ctx-&gt;iv[i &gt;&gt; 2] | iv[i]; ctx-&gt;iv[i &gt;&gt; 2] = ROTL32(ctx-&gt;iv[i &gt;&gt; 2],8); } /* setup the table P and Q */ for (i = 0; i &lt; 8; i++) W[i] = ctx-&gt;key[i]; for (i = 8; i &lt; 16; i++) W[i] = ctx-&gt;iv[i-8]; for (i = 16; i &lt; 2560; i++) W[i] = f2(W[i-2]) + W[i-7] + f1(W[i-15]) + W[i-16]+i; for (i = 0; i &lt; 1024; i++) ctx-&gt;P[i] = W[i+512]; for (i = 0; i &lt; 1024; i++) ctx-&gt;Q[i] = W[i+1536]; ctx-&gt;counter2048 = 0; /* run the cipher 4096 steps before generating the output */ for (i = 0; i &lt; 4096; i++) generate(ctx); } void ECRYPT_keysetup( ECRYPT_ctx* ctx, const u8* key, u32 keysize, /* Key size in bits. */ u32 ivsize) /* IV size in bits. */ { u32 i; ctx-&gt;keysize = keysize &gt;&gt; 3; ctx-&gt;ivsize = ivsize &gt;&gt; 3; for (i = 0; i &lt; 8; i++) ctx-&gt;key[i] = 0; for (i = 0; (i &lt; ctx-&gt;keysize) &amp; (i &lt; 32); i++) { ctx-&gt;key[i &gt;&gt; 2] = ctx-&gt;key[i &gt;&gt; 2] | key[i]; ctx-&gt;key[i &gt;&gt; 2] = ROTL32(ctx-&gt;key[i &gt;&gt; 2],8); } } /* initialize the key, save the iv size*/ u32 generate(ECRYPT_ctx* ctx) /*one step of the cipher*/ { u32 i,i3, i10, i12, i1023; u32 output; i = ctx-&gt;counter2048 &amp; 0x3ff; i3 = (i - 3) &amp; 0x3ff; i10 = (i - 10) &amp; 0x3ff; i12 = (i - 12) &amp; 0x3ff; i1023 = (i - 1023) &amp; 0x3ff; if (ctx-&gt;counter2048 &lt; 1024) { ctx-&gt;P[i] = ctx-&gt;P[i] + ctx-&gt;P[i10] + (ROTR32(ctx-&gt;P[i3],10)^ROTR32(ctx-&gt;P[i1023],23))+ctx-&gt;Q[(ctx-&gt;P[i3]^ctx-&gt;P[i1023])&amp;0x3ff]; output = h1(ctx,ctx-&gt;P[i12]) ^ ctx-&gt;P[i]; } else { ctx-&gt;Q[i] = ctx-&gt;Q[i] + ctx-&gt;Q[i10] + (ROTR32(ctx-&gt;Q[i3],10)^ROTR32(ctx-&gt;Q[i1023],23))+ctx-&gt;P[(ctx-&gt;Q[i3]^ctx-&gt;Q[i1023])&amp;0x3ff]; output = h2(ctx, ctx-&gt;Q[i12]) ^ ctx-&gt;Q[i]; } ctx-&gt;counter2048 = (ctx-&gt;counter2048+1) &amp; 0x7ff; return (output); } u32 h2(ECRYPT_ctx* ctx, u32 u) { u32 tem; unsigned char a,b,c,d; a = (unsigned char) ((u)); b = (unsigned char) ((u) &gt;&gt; 8); c = (unsigned char) ((u) &gt;&gt; 16); d = (unsigned char) ((u) &gt;&gt; 24); tem = ctx-&gt;P[a]+ctx-&gt;P[256+b]+ctx-&gt;P[512+c]+ctx-&gt;P[768+d]; return (tem); } u32 h1(ECRYPT_ctx* ctx, u32 u) { u32 tem; unsigned char a,b,c,d; a = (unsigned char) ((u)); b = (unsigned char) ((u) &gt;&gt; 8); c = (unsigned char) ((u) &gt;&gt; 16); d = (unsigned char) ((u) &gt;&gt; 24); tem = ctx-&gt;Q[a]+ctx-&gt;Q[256+b]+ctx-&gt;Q[512+c]+ctx-&gt;Q[768+d]; return (tem); } #ifdef ECRYPT_USES_DEFAULT_ALL_IN_ONE /* * Default implementation of all-in-one encryption/decryption of * (short) packets. */ #ifdef ECRYPT_HAS_SINGLE_PACKET_FUNCTION void ECRYPT_process_packet( int action, ECRYPT_ctx* ctx, const u8* iv, const u8* input, u8* output, u32 msglen) { ECRYPT_ivsetup(ctx, iv); #ifdef ECRYPT_HAS_SINGLE_BYTE_FUNCTION ECRYPT_process_bytes(action, ctx, input, output, msglen); #else if (action == 0) ECRYPT_encrypt_bytes(ctx, input, output, msglen); else ECRYPT_decrypt_bytes(ctx, input, output, msglen); #endif } #else void ECRYPT_encrypt_packet( ECRYPT_ctx* ctx, const u8* iv, const u8* plaintext, u8* ciphertext, u32 msglen) { ECRYPT_ivsetup(ctx, iv); ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, msglen); } void ECRYPT_decrypt_packet( ECRYPT_ctx* ctx, const u8* iv, const u8* ciphertext, u8* plaintext, u32 msglen) { ECRYPT_ivsetup(ctx, iv); ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, msglen); } #endif #endif </code></pre> <p>And inside "ecrypt-sync.h":</p> <pre><code>/* ecrypt-sync.h */ /* * Header file for synchronous stream ciphers without authentication * mechanism. * * *** Please only edit parts marked with "[edit]". *** */ #include "ecrypt-portable.h" #ifndef ECRYPT_SYNC #define ECRYPT_SYNC /* ------------------------------------------------------------------------- */ /* Cipher parameters */ /* * The name of your cipher. */ #define ECRYPT_NAME "ECRYPT Stream Cipher HC-256" /* [edit] */ /* * Specify which key and IV sizes are supported by your cipher. A user * should be able to enumerate the supported sizes by running the * following code: * * for (i = 0; ECRYPT_KEYSIZE(i) &lt;= ECRYPT_MAXKEYSIZE; ++i) * { * keysize = ECRYPT_KEYSIZE(i); * * ... * } * * All sizes are in bits. */ #define ECRYPT_MAXKEYSIZE 256 /* [edit] */ #define ECRYPT_KEYSIZE(i) (128 + (i)*32) /* [edit] */ #define ECRYPT_MAXIVSIZE 256 /* [edit] */ #define ECRYPT_IVSIZE(i) (64 + (i)*64) /* [edit] */ /* ------------------------------------------------------------------------- */ /* Data structures */ /* * ECRYPT_ctx is the structure containing the representation of the * internal state of your cipher. */ typedef struct { /* * [edit] * * Put here all state variable needed during the encryption process. */ u32 P[1024]; u32 Q[1024]; u32 counter2048; u32 key[8]; u32 iv[8]; u32 keysize; /* key size in bytes */ u32 ivsize; /* iv size in bytes */ } ECRYPT_ctx; /* ------------------------------------------------------------------------- */ /* Mandatory functions */ /* * Key and message independent initialization. This function will be * called once when the program starts (e.g., to build expanded S-box * tables). */ void ECRYPT_init(void); /* * Key setup. It is the user's responsibility to select the values of * keysize and ivsize from the set of supported values specified * above. */ void ECRYPT_keysetup( ECRYPT_ctx* ctx, const u8* key, u32 keysize, /* Key size in bits. */ u32 ivsize); /* IV size in bits. */ /* * IV setup. After having called ECRYPT_keysetup(), the user is * allowed to call ECRYPT_ivsetup() different times in order to * encrypt/decrypt different messages with the same key but different * IV's. */ void ECRYPT_ivsetup( ECRYPT_ctx* ctx, const u8* iv); /* * Encryption/decryption of arbitrary length messages. * * For efficiency reasons, the API provides two types of * encrypt/decrypt functions. The ECRYPT_encrypt_bytes() function * (declared here) encrypts byte strings of arbitrary length, while * the ECRYPT_encrypt_blocks() function (defined later) only accepts * lengths which are multiples of ECRYPT_BLOCKLENGTH. * * The user is allowed to make multiple calls to * ECRYPT_encrypt_blocks() to incrementally encrypt a long message, * but he is NOT allowed to make additional encryption calls once he * has called ECRYPT_encrypt_bytes() (unless he starts a new message * of course). For example, this sequence of calls is acceptable: * * ECRYPT_keysetup(); * * ECRYPT_ivsetup(); * ECRYPT_encrypt_blocks(); * ECRYPT_encrypt_blocks(); * ECRYPT_encrypt_bytes(); * * ECRYPT_ivsetup(); * ECRYPT_encrypt_blocks(); * ECRYPT_encrypt_blocks(); * * ECRYPT_ivsetup(); * ECRYPT_encrypt_bytes(); * * The following sequence is not: * * ECRYPT_keysetup(); * ECRYPT_ivsetup(); * ECRYPT_encrypt_blocks(); * ECRYPT_encrypt_bytes(); * ECRYPT_encrypt_blocks(); */ /* * By default ECRYPT_encrypt_bytes() and ECRYPT_decrypt_bytes() are * defined as macros which redirect the call to a single function * ECRYPT_process_bytes(). If you want to provide separate encryption * and decryption functions, please undef * ECRYPT_HAS_SINGLE_BYTE_FUNCTION. */ #define ECRYPT_HAS_SINGLE_BYTE_FUNCTION 1 /* [edit] */ #ifdef ECRYPT_HAS_SINGLE_BYTE_FUNCTION #define ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, msglen) \ ECRYPT_process_bytes(0, ctx, plaintext, ciphertext, msglen) #define ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, msglen) \ ECRYPT_process_bytes(1, ctx, ciphertext, plaintext, msglen) void ECRYPT_process_bytes( int action, /* 0 = encrypt; 1 = decrypt; */ ECRYPT_ctx* ctx, const u8* input, u8* output, u32 msglen); /* Message length in bytes. */ #else void ECRYPT_encrypt_bytes( ECRYPT_ctx* ctx, const u8* plaintext, u8* ciphertext, u32 msglen); /* Message length in bytes. */ void ECRYPT_decrypt_bytes( ECRYPT_ctx* ctx, const u8* ciphertext, u8* plaintext, u32 msglen); /* Message length in bytes. */ #endif /* ------------------------------------------------------------------------- */ /* Optional features */ /* * For testing purposes it can sometimes be useful to have a function * which immediately generates keystream without having to provide it * with a zero plaintext. If your cipher cannot provide this function * (e.g., because it is not strictly a synchronous cipher), please * reset the ECRYPT_GENERATES_KEYSTREAM flag. */ #define ECRYPT_GENERATES_KEYSTREAM #ifdef ECRYPT_GENERATES_KEYSTREAM void ECRYPT_keystream_bytes( ECRYPT_ctx* ctx, u8* keystream, u32 length); /* Length of keystream in bytes. */ #endif /* ------------------------------------------------------------------------- */ /* Optional optimizations */ /* * By default, the functions in this section are implemented using * calls to functions declared above. However, you might want to * implement them differently for performance reasons. */ /* * All-in-one encryption/decryption of (short) packets. * * The default definitions of these functions can be found in * "ecrypt-sync.c". If you want to implement them differently, please * undef the ECRYPT_USES_DEFAULT_ALL_IN_ONE flag. */ #define ECRYPT_USES_DEFAULT_ALL_IN_ONE /* [edit] */ /* * Undef ECRYPT_HAS_SINGLE_PACKET_FUNCTION if you want to provide * separate packet encryption and decryption functions. */ #define ECRYPT_HAS_SINGLE_PACKET_FUNCTION /* [edit] */ #ifdef ECRYPT_HAS_SINGLE_PACKET_FUNCTION #define ECRYPT_encrypt_packet( \ ctx, iv, plaintext, ciphertext, mglen) \ ECRYPT_process_packet(0, \ ctx, iv, plaintext, ciphertext, mglen) #define ECRYPT_decrypt_packet( \ ctx, iv, ciphertext, plaintext, mglen) \ ECRYPT_process_packet(1, \ ctx, iv, ciphertext, plaintext, mglen) void ECRYPT_process_packet( int action, /* 0 = encrypt; 1 = decrypt; */ ECRYPT_ctx* ctx, const u8* iv, const u8* input, u8* output, u32 msglen); #else void ECRYPT_encrypt_packet( ECRYPT_ctx* ctx, const u8* iv, const u8* plaintext, u8* ciphertext, u32 msglen); void ECRYPT_decrypt_packet( ECRYPT_ctx* ctx, const u8* iv, const u8* ciphertext, u8* plaintext, u32 msglen); #endif /* * Encryption/decryption of blocks. * * By default, these functions are defined as macros. If you want to * provide a different implementation, please undef the * ECRYPT_USES_DEFAULT_BLOCK_MACROS flag and implement the functions * declared below. */ #define ECRYPT_BLOCKLENGTH 4 /* [edit] */ #define ECRYPT_USES_DEFAULT_BLOCK_MACROS /* [edit] */ #ifdef ECRYPT_USES_DEFAULT_BLOCK_MACROS #define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \ ECRYPT_encrypt_bytes(ctx, plaintext, ciphertext, \ (blocks) * ECRYPT_BLOCKLENGTH) #define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \ ECRYPT_decrypt_bytes(ctx, ciphertext, plaintext, \ (blocks) * ECRYPT_BLOCKLENGTH) #ifdef ECRYPT_GENERATES_KEYSTREAM #define ECRYPT_keystream_blocks(ctx, keystream, blocks) \ ECRYPT_keystream_bytes(ctx, keystream, \ (blocks) * ECRYPT_BLOCKLENGTH) #endif #else /* * Undef ECRYPT_HAS_SINGLE_BLOCK_FUNCTION if you want to provide * separate block encryption and decryption functions. */ #define ECRYPT_HAS_SINGLE_BLOCK_FUNCTION /* [edit] */ #ifdef ECRYPT_HAS_SINGLE_BLOCK_FUNCTION #define ECRYPT_encrypt_blocks(ctx, plaintext, ciphertext, blocks) \ ECRYPT_process_blocks(0, ctx, plaintext, ciphertext, blocks) #define ECRYPT_decrypt_blocks(ctx, ciphertext, plaintext, blocks) \ ECRYPT_process_blocks(1, ctx, ciphertext, plaintext, blocks) void ECRYPT_process_blocks( int action, /* 0 = encrypt; 1 = decrypt; */ ECRYPT_ctx* ctx, const u8* input, u8* output, u32 blocks); /* Message length in blocks. */ #else void ECRYPT_encrypt_blocks( ECRYPT_ctx* ctx, const u8* plaintext, u8* ciphertext, u32 blocks); /* Message length in blocks. */ void ECRYPT_decrypt_blocks( ECRYPT_ctx* ctx, const u8* ciphertext, u8* plaintext, u32 blocks); /* Message length in blocks. */ #endif #ifdef ECRYPT_GENERATES_KEYSTREAM void ECRYPT_keystream_blocks( ECRYPT_ctx* ctx, u8* keystream, u32 blocks); /* Keystream length in blocks. */ #endif #endif /* * If your cipher can be implemented in different ways, you can use * the ECRYPT_VARIANT parameter to allow the user to choose between * them at compile time (e.g., gcc -DECRYPT_VARIANT=3 ...). Please * only use this possibility if you really think it could make a * significant difference and keep the number of variants * (ECRYPT_MAXVARIANT) as small as possible (definitely not more than * 10). Note also that all variants should have exactly the same * external interface (i.e., the same ECRYPT_BLOCKLENGTH, etc.). */ #define ECRYPT_MAXVARIANT 1 /* [edit] */ #ifndef ECRYPT_VARIANT #define ECRYPT_VARIANT 1 #endif #if (ECRYPT_VARIANT &gt; ECRYPT_MAXVARIANT) #error this variant does not exist #endif /* ------------------------------------------------------------------------- */ #endif /* =========================================================================== Added functions: HC-256 Mandatory functions ============================================================================== */ #define f1(x) (ROTR32((x),7) ^ ROTR32((x),18) ^ ((x) &gt;&gt; 3)) #define f2(x) (ROTR32((x),17) ^ ROTR32((x),19) ^ ((x) &gt;&gt; 10)) /* void ECRYPT_keysetup( ECRYPT_ctx* ctx, const u8* key, u32 keysize, // Key size in bits. u32 ivsize); // IV size in bits. void ECRYPT_ivsetup( ECRYPT_ctx* ctx, const u8* iv); void ECRYPT_process_bytes( int action, // 0 = encrypt; 1 = decrypt; ECRYPT_ctx* ctx, const u8* input, u8* output, u32 msglen); // Message length in bytes. */ void ECRYPT_init(void); u32 h1(ECRYPT_ctx* ctx, u32 u); u32 h2(ECRYPT_ctx* ctx, u32 u); u32 generate(ECRYPT_ctx* ctx); </code></pre> <p>Then use "ecrypt-machine.h", "ecrypt-config.h", and "ecrypt-portable.h" from here: <a href="http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3source.zip" rel="nofollow">http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3source.zip</a></p> <p>Here is a quick application to test it. You will have to create the "generateRandom" function, or just make up some random bytes lol.</p> <pre><code>#include "crypto.hpp" int main(int argc, char **argv){ CRYPTOSOCKET *socket; unsigned char key[32]; unsigned char iv[32]; unsigned char buf1[1024]; unsigned char buf2[1024]; unsigned char buf3[1024]; char *teststring = "This is a test.\n"; // Generate a random key generateRandom(key, 32); // Generate a random IV generateRandom(iv, 32); // Create a new cryptosocket with that key and iv. socket = new CRYPTOSOCKET(0, key, iv); // Copy teststring into buffer 1 sprintf((char*)buf1,teststring); // Encrypt buffer 1 and placed the encrypted contents into buffer 2. socket-&gt;encrypt(buf1,strlen(teststring), buf2); // Decrypt buffer 2 into buffer 3. socket-&gt;decrypt(buf2, strlen(teststring), buf3); // Print out whats in buffer 3. printf((char*)buf3); } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload