Code Monkey home page Code Monkey logo

Comments (9)

gioblu avatar gioblu commented on August 19, 2024

Ciao @rspencer01 thank you so much for dedicating some time to hack this :)
I agree with you that a 150 characters plaintext encrypted with a 10 characters key is not secure, and that is stated clearly in the README.

I see you assumptions implies:

  • Use an extremely weak configuration (150 characters plaintext encrypted with a tiny 10 characters key).
  • have a partial knowledge of what the content of the string is (excluding to check most of the possible byte values), that is not always the case.
  • Know that the user is using Cape
  • Know that the user is using the encrypt function

How much harder would be without starting from those assumptions to get back the plaintext?

Thank you so much for your support.

from cape.

luke-park avatar luke-park commented on August 19, 2024

I've also looked at the code here and it has a few rather concerning flaws... The whole salt and IV thing doesn't really make any sense (neither are what they say on the box, you could have called them foo and bar). Additionally, encrypting only zero bytes leads almost directly to the keystream, which means any sort of chosen plaintext attack ("in the wild") would break the implementation pretty quickly.

The largest issue is the issue outlined by rspencer01. I say issue lightly here, it is a full break of the algorithm, really. I feel that it is misleading to potential viewers of this repository to not alert them to the fact that the code within doesn't actually provide any security. I second the idea of a banner.

from cape.

gioblu avatar gioblu commented on August 19, 2024

Ciao @rspencer01 @luke-park I am sincerely thankful to you for taking time to study the algorithm and even write some code to demonstrate its vulnerability.

I had a real life issue in the last 2 hours, so I was not able to commit changes, I will for sure add the suggested statement in the README and relate it to this issue.

This repository and its codebase are obviously in experimental state and its procedure for sure not in its definitive state, it is just an experiment.

@rspencer01 I am also eager to finally run your gist and test on longer keys. Thank you again for sharing your experience. I am sure who is following Cape's development will be as happy as me to play with your example.

@luke-park I am sorry, the 00000 string encryption flaw was already described in the reddit, but I have practically tested this afternoon using different keys and both hash and encrypt function but I am not able to get the key as you describe. Quoting myself on reddit:

-/-#%!/-') this is a cipher text generated using the hash function that does not use any IV, its plaintext is 0000000000 and the key is extremely simple. Any idea of the key value?

@luke-park what you mean with

The whole salt and IV thing doesn't really make any sense

from cape.

silkeh avatar silkeh commented on August 19, 2024

@gioblu The problem with encrypting a zero byte string is that this results in a direct correlation between known variables.
The key can be calculated as follows:

srk = salt ^ reduced_key
// For encrypt/decrypt; 0 <= i < message length
key[(srk ^ i) % _key_length] = destination[i] ^ source[i] ^ iv ^ i;
// For hash; 0 <= i < message length
key[(srk ^ i) % _key_length] = destination[i] ^ source[i] ^ srk ^ i;

This means that there is a fairly straightforward way to calculate the key if the source (or any properties of the source) are known.
The only unknowns are the length of the key (which is probably below 256 characters) and the reduced key (8 bits), assuming the salt (and/or IV) are known (though these two only are 8 bits in size).

Brute forcing the unknowns allows a very quick calculation of all valid keys for a message.
Additional messages (even when fairly short) would narrow the list of valid keys down quite quickly.

-/-#%!/-') this is a cipher text generated using the hash function that does not use any IV, its plaintext is 0000000000 and the key is extremely simple. Any idea of the key value?

Sure, the following prints that ciphertext:

#include <iostream>
#include <string>
#include "Cape.h"

int main() {
  char key[] = "e`mnijkd????kd??"; // Undetermined characters were replaced by ?
  char src[]  = {0,0,0,0,0,0,0,0,0,0};
  char dst[255];

  Cape cape(key, std::strlen(key));
  cape.hash(src, dst, 10);

  std::cout << std::string(dst, 10) << std::endl;
}

from cape.

gioblu avatar gioblu commented on August 19, 2024

Ciao @silkeh, thank you so much for your support. I have tried out the proposed calculation starting from hash using key 1234567890, plantext 0000000000 and salt 0 :

calculated_key[(i ^ cape.salt ^ reduced_key) % 10] =
  (destination[i] ^ source[i] ^ cape.salt ^ reduced_key ^  i);

Results show effectively the key for plaintext 0000000000 and 1234567890, but thiskeynot and many others does not output the key, it seems an attack related not only to a finite set of plaintext (0000000000, 1111111111, 2222222222) but also a finite set of keys (0000000000, 1234567890, 2345678901) and salt values:

Key: 0000000000 Cipher: @ABCDEFGHI Computed key: 0000000000 Salt: 0
Key: 1234567890 Cipher: ½¼¿¾¹¸»ºµ´ Computed key: 1234567890 Salt: 0
Key: 2345678901 Cipher: vvzz~~zzvv Computed key: 2345678901 Salt: 0

Then starting from the assumption that the plaintext is known to the attacker, I have used brute force to obtain the salt and I have noticed that more than one value of salt (also not the one is in use) outputs the correct key used for that ciphertext and also that the salt only scrambles the key in any case giving good hints about it.

So absolutely, too few unkowns, weak algorithm and me not taking into consideration the known plaintext attack. 🥇 Thank you and my compliments again @silkeh and @rspencer01 .

I will work on something less vulnerable :)

from cape.

silkeh avatar silkeh commented on August 19, 2024

Good luck!

By the way, watch out for the use of the % operator on negative values.
The following (from encrypt/decrypt) can read _key with a negative index because srk is a (signed) char:

destination[i] = source[i] ^ iv ^ i ^ _key[(srk ^ i) % _key_length];

Additionally, I think the quality of the C++ code could be improved:

  • Make use of std types (like std::string, std::vector and std::array), this simplifies the function arguments, loops and allows easier bounds checks.
  • Declare function arguments as const when they are not modified.
  • Document the code for use with Doxygen
  • Lint and format code (by using tools like clang-tidy and clang-format)

Following the features of a C++ standard (eg: C++11 or C++14) and matching guidelines (eg: http://cginternals.github.io/guidelines/) can help you with this.

from cape.

gioblu avatar gioblu commented on August 19, 2024

@silkeh I have fixed the sign issue, thank you.
I will clean out the warnings, not sure if to be able to comply 100% to the codestyle standard.
I will download the suggested tools and will make better use of std types.
Thank you again for sharing your experience.

from cape.

Pharap avatar Pharap commented on August 19, 2024

Sorry to drag this up again, but I missed it at the time because I forgot to watch the repo.

@silkeh The reason C++ stdlib types aren't used is because this library is used on Arduino and Arduino programs don't have a version of the stdlib, and frankly some Arduino MCUs don't have enough RAM to support the dynamic allocation used by std::vector or std::string.

The const thing is a fair point, but really that ought to be raised as a separate issue.

@rspencer01 I'm glad you managed to make a proof of this.
I had suspected it was possible but didn't raise the issue because I couldn't write a program capable of proving it. I was missing the bit about making assumptions about what the encrypted data looks like, so I was trying a lot of unnecessary permutations.

from cape.

gioblu avatar gioblu commented on August 19, 2024

Ciao @Pharap I agree, I wasn't able to break it too, @rspencer01 gave a great contribution 👍 , extremely instructive. I agree with you @Pharap about std::vector or std::string, it is not the only repository where I was forced to choose so.

from cape.

Related Issues (16)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.