GithubHelp home page GithubHelp logo

prajwalmali / crypto Goto Github PK

View Code? Open in Web Editor NEW
35.0 4.0 5.0 282 KB

This tool will encrypt-decrypt your files and directories. It has built-in password generator and featured with Colourful UI. It is based on AES (Advanced Encryption Standard) CBC mode Algorithm Symmetric Cryptography and made in Python language (Python3)

Home Page: https://prajwalcybergod.github.io/PrajwalCyberGod

Python 100.00%
python cryptography cybersecurity encryption decryption aes cbc hacking ethicalhacking crypto

crypto's Introduction

prajwalmali

Hi πŸ‘‹, I'm Prajwal Vijaykumar Mali

A passionate cybersecurity learner from India

About Me

GIF

  • πŸ”­ I’m currently working on Automation

  • 🌱 I’m currently learning MERN stack

  • πŸ‘¨β€πŸ’» All of my projects are available at My Repos

  • πŸ’» My current BEST project is AutoWhatsApp

  • πŸ’¬ Ask me about Cybersecurity

  • πŸ“« How to reach me [email protected]

  • ⚑ Fun fact I want to be a Hacker and that's why I am in Cybersecurity

  • πŸ“š Currently pursuing Bachelors of Computer Engineering, Third Year [2021-22] [9.3 CGPA]


πŸ”” π™Όπš’ π™»πšŠπšπšŽπšœπš π™Άπš’πšπ™·πšžπš‹ π™ΌπšŽπšπš›πš’πšŒπšœ

prajwalmali

prajwalmali

prajwalmali

prajwalmali

prajwalmali


πŸ”₯ Contributions



T h i n g s I πŸ’š :
P W
D E S I G N H
M Y C I
I C O D E O M
N H L S
I S O C I O L O G Y
M L R
A O
L I N G U I S T I C
I Y E
S X πŸ“Έ
M

Languages and Tools

c cplusplus

d3js

html5

java

javascript

php

python

sqlite




Contact

LinkedIn

PayPal

crypto's People

Contributors

prajwalmali avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

crypto's Issues

Several vulnerabilities in the code

0. No security policy for reporting vulnerabilities

Considering this is client-side software at its infancy, I'm not going to bother going through more formal paths like filing for CVEs. Adding a security policy would be a worthwhile task.

1. No standard disclaimer warning about not to use the code in production

Also, considering the code has not been audited, peer-reviewed or validated in any way, a warning label should be added. There is no shame in doing this. Even professional cryptographers like Boneh et. al. included a warning label to their work-in-progress code:

This is a research protoype of the Balloon space-hard hash function. The code
is still a work in progress. Some (not all) of the parts of the code that need
attention are marked with TODO comments. See the LICENSE file for licensing
information.

Please DO NOT use this code in production!

This is an early research prototype built exclusively for benchmarking purposes
and it is almost certainly riddled with obvious security vulnerabilities. In
the future, if this code gets the level of scrutiny that security-critical
production code deserves, I will remove this warning. Until then, here be
dragons.

2. Using a hard-coded encryption key

The user's password is protected with a hardcoded key spefified on line 116

key = b'[EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e'

This is is a serious vulnerability as the key protects the user's password. Anyone can read the key from the source file and decrypt the password.txt.enc file to obtain the user's password from the first line of the file.

Furthermore, on Line 213 it's apparent the program uses the hard-coded encryption key to encrypt the files determined by the user. Thus, the attacker can decrypt any file without ever knowing the password of the user. The password check only limits how the program you wrote, works. It's trivial to edit the code to not ask for password, or to write another program that uses the hardcoded key to decrypt the files specified by the attacker. It takes exactly five lines of code:

from Crypto.Cipher import AES
with open(input("give /path/to/ciphertext: "), 'rb') as f:
    ciphertext = f.read() 
    cipher = AES.new(b'[EX\xc8\xd5\xbfI{\xa2$\x05(\xd5\x18\xbf\xc0\x85)\x10nc\x94\x02)j\xdf\xcb\xc4\x94\x9d(\x9e', AES.MODE_CBC, ciphertext[:AES.block_size])
    print(cipher.decrypt(ciphertext[AES.block_size:]))

The best practice for password protected encryption is to

  1. Derive the encryption key from password and salt with a slow hash function such as Argon2, and
  2. Test the validity of the password by either attempting to decrypt the file and raising exception about faulty password when the authentication operation performed during decryption of ciphertext fails, or, prior to decryption, to compare the digest of the derived key against its cryptographic (e.g. SHA256) digest, stored in some login file.

3. Using AES-CBC without authentication

Because the ciphertext is encrypted with AES-CBC, and no message authentication code (such as HMAC-SHA256) is used, any tampering of the ciphertext will result in program blindly trusting the altered data to be authentic.

The best practice is to switch AES-CBC to some authenticated encryption scheme (AEAD), that is, XSalsa20-Poly1305, XChaCha20-Poly1305, or AES-GCM. The recommended libraries to use are those by the PyCa, i.e. https://github.com/pyca/cryptography or https://github.com/pyca/pynacl.

An alternative way is to authenticate the AES-CBC ciphertext with e.g. HMAC-SHA256 but considering your perceived implementation skills, an AEAD cipher is faster to implement, and more difficult to get wrong and thus more safe.

4. Writing plaintext password to a file

On Line 79 of script.py the decrypted password is written to a file. I'm assuming the program is running with user level privileges here. The decrypted file can be read by any program with user-level privileges before it is deleted by the os.remove() operation of a subsequent encrypt_file() function call. It is worth mentioning the os.remove() call will not overwrite data on disk. Thus, due to data remanence the data is still going to remain on disk, and furthermore, due to SSDs performing wear leveling it's not possible to reliably overwrite data from disk on modern computers.

Writing sensitive data in a plaintext file is an incorrect way to implement password check. This part of the code should be removed completely.

5. Faulty implementation of zero-padding

The pad-function appends zero-bytes to the plaintext until its length matches the next block size.

On Line 67

return plaintext.rstrip(b"\0")

The decrypt() function removes all zero-bytes. This will corrupt any plaintext that ended in trailing zero-bytes.

The best practice is to either switch to an authenticating stream cipher like XSalsa20-Poly1305 or XChaCha20-Poly1305 that requires no padding, and/or to use PKCS#7 padding to make the plaintext length a multiple of the cipher's block size.

6. Not using cryptographically secure random number generator to generate password

On Line 380 password is generated with

password = "".join(random.sample(s, plen))

The random module's documentation states the following

Warning: The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module.

The choice of RNG is discussed as part of the next section.

7. Not using uniform sampling to generate the password.

Furthermore, the .sample() method is defined to function as follows:

Return a k length list of unique elements chosen from the population sequence or set. Used for random sampling without replacement.

This means that the created password will not have uniformly random distribution, i.e. where the entropy of the password is log2(charspace^length).

Instead, it'll have entropy of log2( charspace * charspace-1 * charspace-2 * charspace-3 * ... * charspace-(n-1) ) where n is the length of the password. This means that when an attacker brute forces the password, they know the next password character is guaranteed not to be any of the previously used characters. So for example with 40-char passwords that are supposed to exceed 256 bits:

import math
import string

def entropy_in_random_sample_pwd(pwd_length: int) -> float:
    charspace = len(string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation)
    number_of_passwords = 1
    for i in range(pwd_length, 0, -1):
        number_of_passwords *= charspace
        charspace -= 1
    entropy = math.log2(number_of_passwords)
    return entropy

def entropy_in_uniform_pwd(pwd_length: int) -> float:
    charspace = len(string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation)
    entropy = math.log2(charspace ** pwd_length)
    return entropy

password_length = 40

print(f"Uniform: {entropy_in_uniform_pwd(password_length)}")
print(f"Sample:  {entropy_in_random_sample_pwd(password_length)}")

You'll notice that only the uniform sampling would exceed the value. Using .sample() method will produce "only" 248-bit password:

Uniform: 262.1835540671055
Sample:  248.05852860442147

While the choices() method aims to produce a uniformly random distribution and initially appears elegant (it fooled me too if you see edit history of this ticket):

Return a k sized list of elements chosen from the population with replacement.

The documentation also says:

For a given seed, the choices() function with equal weighting typically produces a different sequence than repeated calls to choice(). The algorithm used by choices() uses floating point arithmetic for internal consistency and speed. The algorithm used by choice() defaults to integer arithmetic with repeated selections to avoid small biases from round-off error.

So the choices() method has biases even when initialized with SystemRandom(). The only option you have is the repeated call of the choice() method. This is consistent with the recipes for best practices for the secrets module:

password = ''.join(secrets.choice(alphabet) for i in range(8))

While random.SystemRandom().choice is secure, and while the secrets.choice() is only a wrapper for random.SystemRandom().choice(), it gives off better impression, and is harder to misuse, so it's a better choice.

Considering an average user tends to choose weak passwords, and any random password you generate for the user means they're probably going to copy-paste the password into a password manager, or at the very least, they're going to write it down. So I would recommend you set the security level (i.e. bit strength) of the password in the app. Tl;dr create the password with

import math
import secrets

password_entropy_bits = 256

password_chars  = string.ascii_lowercase + string.ascii_uppercase + string.digits + string.punctuation
password_length = math.ceil(math.log(2 ** password_entropy_bits, len(password_chars)))
password        = ''.join(secrets.choice(password_chars) for _ in range(password_chars))

8. Using an unmaintained crypto library

https://www.dlitz.net/software/pycrypto/ links to its GitHub page https://github.com/pycrypto/pycrypto. From there you can see the crypto library hasn't received updates for 7 years. It is highly recommended you switch to either pyca/cryptography which is a maintained and well-respected wrapper for OpenSSL, or pyca/pynacl which provides bindings for the well-respected libsodium library.

9. Security review of the code is a bit difficult due to non-pythonic code (auditability)

PEP8 is a style guide, not a weapon, but still, I would advice you to

  • avoid excessive new-lines. Group together lines that complete some concrete task
  • avoid camelCasing
  • use 4 space indents instead of tabs
  • add docstrings to methods and functions
  • add type annotations (makes life with IDEs easier)
  • split the "main program" (i.e. lines 124..430) to multiple functions to improve readability

8. Ensure data gets written on disk (availability)

Here's an example of a function that ensures data is written all the way on the disk as opposed to the program's buffer.

def write_to_file(file_name: str, data: bytes) -> None:
    """Write data to file."""
    with open(file_name, 'wb+') as f:
        f.write(data)

        # Write data from program buffer to operating system buffer.
        f.flush()

        # Run the fsync syscall to ensure operating system buffer is
        # synchronized with storage device, i.e. write the data on disk.
        # https://docs.python.org/3/library/os.html#os.fsync
        # http://man7.org/linux/man-pages/man2/fdatasync.2.html
        os.fsync(f.fileno())

Conclusion

It takes a LOT of expertise to implement cryptography safely with such low-level primitives. One great way to start is to read literature on the topic with increasing complexity, until you have better grasp about what you know you know, and especially what you know you don't yet know. My recommended reading order is

  1. https://www.crypto101.io/
  2. https://nostarch.com/seriouscrypto
  3. https://online.stanford.edu/courses/soe-y0001-cryptography-i
  4. https://toc.cryptobook.us/book.pdf

Also do note that this issue is not an audit. Your code is not guaranteed to be secure for production use even when the issues are fixed. This was only a cursory look into the code, not a thorough security review. So keep the warning label discussed in section 1 and keep learning. πŸ‘

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.