• Breaking News

    Wednesday, February 21, 2018

    Cryptography I designed a block cipher for fun

    Cryptography I designed a block cipher for fun


    I designed a block cipher for fun

    Posted: 20 Feb 2018 03:37 PM PST

    This is a block cipher I made in my spare time over the past few weeks. It's a sort of hybrid Feistel network that encrypts 128-bit blocks, currently only using 128 bit keys. The cipher alternates between four rounds of Feistel-like operations ("subrounds") and a substitution round, where all bytes in the block are replaced with their corresponding byte in an S-box.

    (Excuse my poor diagrams)

    The subround operation looks like this: diagram

    where f is a function, specifically called the remap function, that takes in two 32-bit words and outputs a third 32-bit word. Subrounds always appear in chunks of four.

    Overall the subround routine is performed twenty times, requiring twenty 32-bit subround keys. The key expansion uses the same remap function, and looks like this: diagram

    It continues to create words and append them to the expanded key using the same pattern:

    key[word_i] = remap(key[word_i-1], key[word_i-4]) 

    assuming there were 4 words provided by the original key.

    Finally, the actual remap function looks like this: diagram

    Input words i and w create output word o. The K values are a set of 32 unique byte constants, intended to prevent repetitive input words like (1a1a1a1a, 3b3b3b3b) from producing patterns in output words. Their actual values do not matter. In my implementation, they are initialized to Pi converted to hexadecimal, with duplicates and 00s removed. This diagram is actually pretty difficult to follow, so here is the function in C:

    void remap(const byte i[WORD_SIZE], const byte w[WORD_SIZE], byte o[WORD_SIZE]) { unsigned char k = 0; for (unsigned char b = 0; b < WORD_SIZE; b++) { o[b] = 0; for (unsigned char j = 0; j < WORD_SIZE; j++) { unsigned char offset = (b + j) % WORD_SIZE; byte x = S[ K[k] ^ i[offset] ] + S[ K[k + 1] ^ w[offset] ]; o[b] += (x >> j) | (x << (8 - j)); // x rotated right by j k += 2; } } } 

    The whole cipher works like this:

    0) Key expansion to 20 words (subround keys) 1) Repeated four times: 1) Four subrounds 2) Substitution round 2) Final four subrounds 

    for a total of twenty subrounds and four substitution rounds. The last substitution round is omitted because it adds no extra security. Blocks should be padded to 128 bits using PKCS#7 padding.

    Here is a walkthrough of encrypting a block: pastebin

    To test the design, I made an executable that encrypts infinite 0x00s in CBC mode with a key of all 0x00s and piped this into dieharder. The results are available here: pastebin

    Then I did the same test using counter mode starting from { 0 } instead, the output for this is here: pastebin

    Next, I encrypted 100MB of 0x00s with a key of 0x00s using CBC with an IV of all 0x00s, and tried to compress the output file with 7zip, xz, and the Windows default zip tool. For all of them, the size of the file increased after compression.

    Here are some test blocks:

    Plaintext Key Ciphertext ================================================================================================== 00000000000000000000000000000000 00000000000000000000000000000000 1eec83a5902e493481620cad1112f76e 00000000000000000000000000000001 00000000000000000000000000000000 8b3e21ad258b1634c7ab796b5b3dd2cd 00000000000000000000000000000000 00000000000000000000000000000001 c066d085bd4332f1de61a84c623739cb 00000000000000000000000000000001 00000000000000000000000000000001 56501415e8e9345d39b692e234320734 ffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff ae5b98a4efa5bc1f44fe9cfe517e1934 fffffffffffffffffffffffffffffffe ffffffffffffffffffffffffffffffff cfba2bd260e0c869068b4f6ee32fc384 

    (Thanks to /u/naclo3samuel for these test ideas)

    The C header file I made is available here: pastebin

    And here's a simple program to run it:

    #include <stdio.h> #include "wildfire-2.h" // 'byte' type defined here int main(void) { byte key[16] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; size_t key_len = 16; byte pt[BLOCK_SIZE] = "Hello world\x00\x04\x04\x04\x04"; byte ct[BLOCK_SIZE] = { 0 }; byte dt[BLOCK_SIZE] = { 0 }; printf("Plaintext: %s\n", pt); encrypt_block(pt, ct, key, key_len); printf("Ciphertext: "); for (int i = 0; i < BLOCK_SIZE; i++) { printf("%02x", ct[i]); } printf("\n"); decrypt_block(ct, dt, key, key_len); printf("Decrypted text: %s\n", dt); return 0; } 

    Disclaimer, I'm aware of Schneier's Law, this was all done for fun/learning, and I'd love to see somebody smarter than me break it. My possible concerns are the remap function being invertible, predictable, or biased in some way, but I myself can't see a way to exploit this.

    submitted by /u/crypto_dummy
    [link] [comments]

    Approximate quantum cloning (PQC): The new way of eavesdropping in quantum cryptography

    Posted: 20 Feb 2018 10:26 AM PST

    Is using a VPN for VoIP calls more or less secure?

    Posted: 20 Feb 2018 02:32 AM PST

    I use a mobile app called Telegram Signal to make end to end VoIP encrypted calls, to hide my IP I use a third party VPN paid provider before calling. Does anybody know if this set up makes it possible for the VPN provider to decrypt my calls with some kind of man in the middle attack?

    I am trying to work out if it is worthwhile for me to use a VPN to place VoIP calls, I don´t really need to hide my IP but since I already have a provider, the idea was that I might as well do it as long as call encryption is not weakened.

    submitted by /u/malcarada
    [link] [comments]

    No comments:

    Post a Comment