/r/cryptography
For people interested in the mathematical and theoretical side of modern cryptography.
From Greek κρύπτω krýpto "hidden" and the verb γράφω gráfo "to write" or λέγειν legein "to speak".
Cryptography is the practice of establishing a secure connection between two parties in the presence of a third party whom you don't want to be able to read your messages.
Cryptographers design algorithms and protocols, which do exactly this (and many other things). They also use a lot of time looking for security holes in existing protocols to make sure they can still be trusted. This is called cryptanalysis.
If you want a formal introduction to cryptography, you should read An Introduction to Mathematical Cryptography. The creator of the sub also approve of the Udacity course Applied Cryptography - A Science of Secrets.
A combined karma of at least 10 is required to post or comment in this sub.
Cryptocurrency talk is only allowed if it's to discuss the cryptography subparts of it.
We won't do your homework for you. It is however allowed to help you understand material and or the questions.
we won't solve your ciphers unless you provide us with an algorithm. If anyone sends you a code or a cipher without telling you how they encrypted it, don't bother posting it on this subreddit - your post will get deleted. We redirect you to /r/breakmycode or /r/codes. Thank you for your understanding and for following the rules.
Related Subreddits:
/r/cryptography
The reason why I am asking this question is that i am afraid if EsLock by Es file explorer might discontinue it's services in future and I will never be able to decrypt my files with .eslock extension
Let's say I have access to the following information:
Wouldn't this be enough parameters to calculate the master secret for the exchange?
It's hard to find a difinitive answer online.
Hi everyone, I’m working on a school project due the day after tomorrow, and I really need help with implementing AES-128 encryption and decryption for files in Python without using the aes library so I’m implementing all AES functions from scratch—such as SubBytes
, MixColumns
, ShiftRows
, and AddRoundKey
.
So far, I’ve managed to get the encryption part working (or at least I think it’s correct), but I’m completely stuck on decryption. I’m not sure if the issue is because of something in the encryption step or if there’s a problem in how I’m handling the decryption.I’ve tried several approaches for decryption, but the output remains encrypted—I’m not getting the original file back.
Here’s what’s happening:
Any tips, resources, or even an outline of the decryption process would mean a lot. Thanks in advance for your help!
Is it possible to create a web platform where users can create 2-of-2 MPC wallets with the platform, allowing two users to swap ownership or participation in their MPC wallets with their counterparties' MPC wallets?
The only trust required from users is that the platform will not lose its key share, but it should be technically impossible for one user to collude with the platform to deceive the other user.
At first was thinking Bob and Alice just reveal their key shares, and notify the platfrom, then they perform
keyshare rotation (that keeps wallet address the same) to their new mpc, problem is this requires to much
trusts in the platform, to do the internal ownership recording, platfrom should just be trusted to not lose the keys
no ownership management.
I have an existential question about how to securely store a password on physical paper. I have thought of creating a Python script to encrypt passwords using the One-Time Pad method, employing the "secrets" library, which is supposed to be cryptographically secure. Is this a suitable approach, and are there any additional recommendations regarding encryption or fragmentation techniques that could protect the information in case of loss or unauthorized access?
I am thinking about a problem on pseudo-random permutations (PRPs). In the real world, we can instantiate PRPs with AES. Suppose you fix an input m, then choose a random key k, and compute the output (cipher) c.
I want to prove that it is hard for any probabilistic polynomial-time (PPT) adversary, with inputs m and c, to come up with any key k′, which may or may not be equal to k, such that applying k′ on m yields the same c.
Any idea for a formal proof?
Thought I'd try implementing this out today and just a have doubt on the highlow part, like what exactly is the use of it? More like a standard? , and is this the right way to do this? I mean negating the sig
import tinyec.ec as ec
from tinyec import registry
curve = registry.get_curve('secp256k1')
privateKey = 0xF94A840F1E1A901843A75DD07FFCC5C84478DC4F987797474C9393AC53AB55E6
publicKey = privateKey*curve.g
messageHash = 0x13ad049fc58fa4b7793f5c40e1c64d71c2b4d05495b76f6c93cd4a6628270115
randomNum = 0x195a7f57ff7d92860c7080966e98e011d53ee516f0ac9fcf64f9f9b1b46b75a4
randomPoint = randomNum*curve.g
randomPointX = randomPoint.x
# s = k^-1(z+dr) where k is randomPoint and z is message hash , d=privateKey and r is the x coordinate of the point
kInverse = pow(randomNum, -1, curve.field.n)
dr = (privateKey*randomPointX) % curve.field.n
signature = kInverse*(messageHash+dr) % curve.field.n
def getHighLow(s):
half = curve.field.n//2
if(s>half):
newSig = (curve.field.n-signature)
return newSig
else:
return s
signature = getHighLow(signature)
print("r: ", randomPointX)
print("s: ", signature)
sigInverse = pow(signature, -1, curve.field.n)
# r = (s^-1*z)G + (s^-1*r)Q , where s is signature, z is
# messagehash and r is the x coordinate of random point and Q the public key
p1 = ((messageHash * sigInverse) % curve.field.n)*curve.g
p2 = ((randomPointX * sigInverse) % curve.field.n)*publicKey
point = (p1+p2).x
print("The point after verifiction is: ",point)
if(randomPointX==point):
print("Successfull signature verification")
Hi all,
I'm doing an evaluation for a client using online and offline Certificate Authorities that move requests between each other using Certificate Management over CMS (CMC) in a combination of HTTPS and file uploads.
I'm struggling to get my head round the RFCs and how to format the requests -- is there recommended reading or learning anyone can point me to?
I just wrote an article on the current practicality of using Homomorphic Encryption (HE) for neural network inference.
There’s plenty of AI-generated slop online about how HE is going to revolutionise AI, but I couldn’t find any posts that explain where it is currently at, with examples.
Let me know what you think!
Given any (amount of) input(s), can it generate every uint32 value? So imagine it just returned the input + 1, then it can generate every value (Given the input is also an uint32, and it overflows to 0). I haven't been able to find any answer online so far.
EDIT: specifically a/the string version https://github.com/dim13/djb2/blob/master/djb2.go#L46-L48
Hi! I have a bit of an unusual question for you all. I'm writing a novel, and a particular letter is encrypted; the password, for narrative reasons, can't be too complicated. It has to be something that can be guessed by one specific person with extremely little in the way of hints. Still, it needs to be resilient to brute-force attacks of a reasonable scale. So here's my question:
What would be the most secure cypher to use, if the key was limited to a short word (8 letters) with the first letter capitalized? The letter is an in-world brand, which means it's relatively known, but not a strictly 'dictionary' word. Anything goes. The body of the letter is normal text, about two pages worth.
Also, feel very free and encouraged to come up with a possible name, or even how it would function, for a near-future cypher that could be resilient to quantum-computer based brute force attacks.
Thank you very much for your expertise :)
Hello.
I am currently researching the Metropolis-Hastings algorithm as a basis for attacking very basic ciphers but I am wondering, down the road, does anyone have some ideas for some more interesting ciphers to try and crack via this method?
Any suggestions appreciated, thanks.
If anyone is trying an exercise on recreating the Enigma machine, here are some of the pitfalls that are simply not understanding how the machine works and I think should be more clearly explained on the internet. This post may be useful for understanding rotor offset, ring settings, notch points, and the double step effect.
I struggled to understand these concepts when trying to code my own Enigma machine in python. I'm not going into the details of how the enigma machine wirings and set up works, but if you're struggling with understanding some of the enigma concepts, this hopefully will help.
The operator sets some initial settings:
The operator uses a keyboard to type their message, and the resulting encrypted letter would be highlighted for them.
Assuming a set up of rotors I, II, III (III being the right most / first rotor the signal is passed through).
How you code the enigma machine is up to you, but these are some key concepts that are not clearly explained on the internet for something as well documented as the enigma machine.
Please let me know if my understanding is incorrect, but this has been my necessary understanding for my code to be successful.
I'm looking for one more complex than a simple character substitution or Caesar cipher. I was hoping for something that can be used to wright in a notebook over large portions of text without being too time consuming.
Hey I have an application that stores hashed password with bcrypt, but I have to keep cost to 4 i.e rounds of salt will be 2^4. I completly understands that this reduces the amount of times needed to brute force the password, but in reality what does that translate to?
Assuming password used is very long one (can be 40 char of [upper/lower/digit/special char] if I want), if a malicious actor gets a hold of hashed value, is it possible to brute force the password in reasonable time (i.e < many years)?
I designed an enigma-style algorithm in C that emulates how the original enigma machine worked in WWII. However, given that it's possible to use plaintext attacks or other methods to break it, or even just brute force it with a modern computer in hours or minutes, I decided to up the ante. I created a new version of enigma that has a 94 character alphabet (uppercase, lowercase, numbers, punctuation, spaces) and any number of gears (10 for now). Even still, I decided to ask ChatGPT to see how feasible it would be to crack it with a supercomputer of sorts and I got an estimate of about 1-2 years.
This leads me to my actual question, is it possible to beat the difficulty of some post-quantum techniques or SHA256 hashing methods by just adding more gears or using a larger alphabet? What if I used 20 gears? 100? 1000? How long would it take for a supercomputer or even a quantum computer to crack it?
EDIT: Some of y'all need to calm down. The reason why I'm asking this in the first place is because I don't know anything about cryptology. Yes, I know that LLMs like ChatGPT are not reliable blah blah blah. I didn't know I was in university. Because I am so new at this, idk what to assume, idk where to look, and idk any of the math to answer my question. I could make the same argument against any of y'all about some niche topic also. My best guess is about as good as my pet rock.
So, ciphers and such have always interested me, so for fun I did some research and programmed a basic encryption/decryption scheme. Thought I'd see if anyone had any thoughts on it by trying to explain it. (Obviously amateur and it is super flawed).
The premise is take the message, create a random key of equal length using combination of 64 unique 6-bit (weaker version of ASCII) characters.
You then XOR the key and plaintext to create a cipher text using the 6-bit character map. The message is deleted.
You create a Diffie-Hellman key, and using the binary of the number you further XOR the key. Then both the key and ciphertext are converted back to the 64 characters.
These are then both further encrypted by giving each character a unique non repeating character out of around 3000 characters. (This is probably a weak unnecessary step since substitution is weak, it is mainly to obfuscate any possible frequency patterns). These are encrypted with the shared secret number.
Voila! That is my brainchild of the last two days. I implemented it in code as well
Hello everyone.
This post is really just for exchanging thoughts, but I've been pondering for a while that in TLS 1.3, block ciphers are no longer used in the traditional sense. Instead, only stream ciphers like ChaCha or AES in a mode that turns it into a stream cipher (GCM, CCM) are employed. I am aware of the advantages (parallel processing) and also understand that CBC mode has caused problems in the past.
However, I don't find this approach entirely unproblematic because, especially in protocols where the plaintext is partially identical or known, parts of the keystream can be easily determined. As long as everything is done correctly, this isn't so critical, of course. But while with AES and CBC mode, one would have done little wrong even if the nonce wasn't entirely random, reusing a nonce in GCM/CCM is quite fatal—even if TLS presumably doesn't make mistakes in this regard.
So, my question is simply how you see it.
A while back I came across a crypto tutorial that covered most crypto concepts using linux command line tools (`openssl_client` etc). I can't find the blog post now, do any of you know which blog post I'm talking about?
Thanks!
So there was a govt election in Georgia yesterday and the reports are that some people were able to vote more than once.
This year elections were held mostly "electronically", the process worked something like this:
On the voting station first they check your hands with UV lights (To see if you were on the elections somewhere else)
Then they take your ID and use it to verify that you are supposed to vote on that station, at this point some piece of paper is printed, you sign it and one of your fingers gets sprayed with fluorescent fluid.
You are given a ballot where you color your choice and later insert it into the machine that stores and counts all the ballots (ballots are later recounted by hand).
Now there are several problems with this system:
Some people did not get sprayed with fluorescent fluid making it possible for them to enter different polling stations. There are reports that their IDs could have been preloaded on verification machines on different stations and they would be able to vote on all of these stations because verification machines were not connected and it did not check if an ID had voted somewhere else.
Frequently the ID card reader did not work (it did not work for me for example) so someone had to enter the id number manually. There are reports that people turned up with different ids just written on a piece of paper inside their passport and those were just entered manually.
The ballots are not connected with you in any way, in theory if someone was to give you 2 ballots and the observers were to look the other way you could just vote twice.
Now, as you can see the week point in the system we have here is the people, be it not spraying fluorescent fluid, entering some id manually or looking the other way. I was thinking if one could come up with some system that would eliminate as much human factor as as possible, (perhaps there is already such a system you are welcome to educate me on that).
Primarily, I was wondering if it would be possible to create such a system that requires minimum trust in documents, people etc, where one human can vote only once, without revealing their exact ballot. So this would require some sort of biometric verification.
One way I guess would be to have something similar to apple face id, which would only let you drop your ballot in the counting machine if it could not find you in the list of people who already voted.
Another way I was thinking about is as follows:
Some biometric data unique to you is used to generate a seed on the polling station (Using some sort of hash function)
The seed is used to generate a huge random number, which gets printed on your ballot
If the person goes to another station the generated random number there will be different but we should be able to determine if already cast ballot contained a random number generated from the same seed.
Given the numbers you can not guess the seed but you can say that the two numbers were generated with the same seed.
The thing I do not like about this is that it would be possible for someone to obtain your biometric info by force and use it to generate another random number that would link you to your ballot, so perhaps some sort of temporary biometric data is required, i do not know of such thing.
Anyway what are your thoughts? Can something similar to what I described be created? Or maybe something even better? Can the problem with being able to link someone with their ballot be solved?
Edit: This is what claude 3.5 came up with https://privatebin.net/?cfbee801c692548b#8eG6Pt5zk8azAMZjpcyoAn1DQPS4DnSE55SCEWozqSKQ
Problem context:
I need a construct that allows generating membership proofs meant to be held on devices that can only send but not receive data, thus they only know the initially configured proof/witness.
The construction should be updatable without requiring the devices to update their proofs/witnesses as they won't be aware of the accumulator update. Updates can be add-only or add-remove, it does not matter.
Devices need to be able to prove set membership to the accumulator holder even after the accumulator has been updated multiples times without the device being aware of the updates. If the accumulator supports add and remove operations, devices holding a proof for a removed element should be deemed invalid by third parties knowing the current "accumulator" value while proofs for en element still in the set should maintain validity.
I am aware of Bloom filters but they do not satisfy my needs as their performance (false acceptance rate) increases the more items you have accumulated.
university student wondering whether I should take graph theory before cryptography class. I've heard that it isnt absolutely necessary as the class should cover it, but wanted to get a second opinon. Thanks
(xpriv G) + (ypriv G) = (xpriv + ypriv) G
G generator point
xpriv, ypriv is integer from Fp finite field (p curve order)
+ is actually + mod p
if this is true, is the following also true:
Bob can generate ethereum (ECDSA) keypair, and share his pub key with Alice,
Alice can generate keypair and share pub key with Bob.
they can generate unified pub key by adding (ec point addition) those two pub keys, and from it
generate valid ethereum account address.
while they keep their private keys secret, wallet address is watch-only, no single individual can sign transactions
and move assets from that address. Only way to reconstruct private key for that wallet(account) address
is for both Bobs and Alices private keys to be added (integer addition in Fp)
Is this know fact ? I want to make a centralized system
but without custody of users wallets, so idea was to generate deposit addresses,
and private keys for deposit addresses can only be constructed when both users and my centralized system
agree on reveailing privay keys to each other.
Please tell me can this work, is it already implemented somewhere, is it wrong ?
Hi everyone,
I'm really interested in cryptography and curious about how others have used it in their work or projects. Cryptography has many applications and possibilities, from securing important information to creating new tech solutions.
Can you share how you've used cryptography in your job or personal projects? What challenges and successes did you encounter along the way? I'd love to hear your experiences and insights.
I have developed a free (no BS, no catch) mini-course to teach full-stack developers about cryptographic concepts that they might encounter in their daily developer life -- encryption, password hashes, salts, PBKDF-2, rainbow table attacks (more to come if devs love it).
This subreddit has some of the most involved cryptographic minds. It will be my pleasure if you can take some time around to go through the course material and give me your critical feedback. There's a feedback form at the end of every lesson.
I will be iterating on the content based on your feedback. I will respect your time and feedback!
Looking forward to all of your thoughts.
Here's the link to the course -- https://cryptography-for-devs.github.io
Hello guys,
The task is "simple". Using the RSA keys that you generate (you make your own implementation of it) encrypt and decrypt files such as .txt, .png, .pdf etc... The problem is that it works fully for .txt files. For .pdf files it work ok (few pages are corrupted) but for a pdf that has 120 pages and 2 pages are corrupt is awesome. But for png files, i get the first quarter rendered well and then it starts becoming corrupted. Im providing you with the code above and really do thank everyone!!! I need to do it with BigInteger, and i have to chunk the data to log2(n) chunk size.
public static BigInteger calculateN(BigInteger p, BigInteger q) {
return p.multiply(q);
}
public static BigInteger calculateFi(BigInteger p, BigInteger q) {
return (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
}
public static BigInteger gcd(BigInteger a, BigInteger b) {
if (b.equals(BigInteger.ZERO)) {
return a;
}
return gcd(b, a.mod(b));
}
public static BigInteger chooseE(BigInteger p, BigInteger q) {
BigInteger fi = calculateFi(p, q);
for (BigInteger e = BigInteger.valueOf(3); e.compareTo(fi) < 0; e = e.add(BigInteger.TWO)) {
if (gcd(e, fi).equals(BigInteger.ONE)) {
return e;
}
}
return BigInteger.valueOf(-1);
}
public static BigInteger modInverse(BigInteger e, BigInteger fi) {
BigInteger m0 = fi;
BigInteger y = BigInteger.ZERO;
BigInteger x = BigInteger.ONE;
if (fi.equals(BigInteger.ONE)) return BigInteger.ZERO;
while (e.compareTo(BigInteger.ONE) > 0) {
BigInteger q = e.divide(fi);
BigInteger t = fi;
fi = e.mod(fi);
e = t;
t = y;
y = x.subtract(q.multiply(y));
x = t;
}
if (x.compareTo(BigInteger.ZERO) < 0) {
x = x.add(m0);
}
return x;
}
public static BigInteger calculateD(BigInteger e, BigInteger fi){
return modInverse(e,fi);
}
private static ArrayList<BigInteger> readKey(String fileName) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(fileName));
String line = br.readLine();
br.close();
String[] parts = line.replaceAll("[^0-9,]", "").split(",");
ArrayList<BigInteger> key = new ArrayList<>();
BigInteger first = new BigInteger(parts[0].trim());
BigInteger second = new BigInteger(parts[1].trim());
System.out.println(first);
System.out.println(second);
key.add(first);
key.add(second);
return key;
}
public static void generateKeys(int bits) {
ArrayList<BigInteger> generatedNumbers = generate2PrimesUsingMillerRabinTest(5, bits);
if (generatedNumbers.size() < 2) {
throw new IllegalStateException("Failed to generate two primes");
}
BigInteger p = generatedNumbers.get(0);
BigInteger q = generatedNumbers.get(1);
System.out.println("First p : " + p + " Second q : " + q);
BigInteger n = calculateN(p, q);
System.out.println("N is : " + n);
BigInteger fi = calculateFi(p, q);
System.out.println("Fi is : " + fi);
BigInteger e = chooseE(p, q);
System.out.println("E is : " + e);
if (e == null) {
throw new IllegalStateException("Failed to find e");
}
BigInteger d = calculateD(e, fi);
System.out.println("D is : " + d);
// Prepare keys for saving
String publicKey = "(" + e + ", " + n + ")\n";
String privateKey = "(" + d + ", " + n + ")\n";
// Save public key to pubkey.txt
try (BufferedWriter writer = new BufferedWriter(new FileWriter("pubkey.txt"))) {
writer.write(publicKey);
} catch (IOException ex) {
System.err.println("Error writing public key to file: " + ex.getMessage());
}
try (BufferedWriter writer = new BufferedWriter(new FileWriter("privkey.txt"))) {
writer.write(privateKey);
} catch (IOException ex) {
System.err.println("Error writing private key to file: " + ex.getMessage());
}
System.out.println(publicKey);
System.out.println(privateKey);
}
public static void encrypt(String inputFile, String outputFile) throws IOException {
ArrayList<BigInteger> key = readKey("pubkey.txt");
BigInteger e = key.get(0);
BigInteger n = key.get(1);
try (FileInputStream fis = new FileInputStream(inputFile);
DataOutputStream dos = new DataOutputStream(new FileOutputStream(outputFile))) {
// Calculate chunk size based on n (log2(n))
long chunkSize = n.bitLength();
int byteChunkSize = (int) Math.floor((double) chunkSize / 8);
byte[] buffer = new byte[byteChunkSize];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
byte[] dataChunk = new byte[bytesRead];
System.arraycopy(buffer, 0, dataChunk, 0, bytesRead);
BigInteger messageChunk = new BigInteger(1, dataChunk);
BigInteger encryptedChunk = messageChunk.modPow(e, n);
byte[] encryptedBytes = encryptedChunk.toByteArray();
dos.writeInt(encryptedBytes.length);
dos.write(encryptedBytes);
}
}
System.out.println("Encryption completed. Encrypted data saved to " + outputFile);
}
public static void decrypt(String inputFile, String outputFile) throws IOException {
ArrayList<BigInteger> key = readKey("privkey.txt");
BigInteger d = key.get(0);
BigInteger n = key.get(1);
System.out.println(n.doubleValue() + " Double");
System.out.println(n.longValue() + " INT");
try (DataInputStream dis = new DataInputStream(new FileInputStream(inputFile));
FileOutputStream fos = new FileOutputStream(outputFile)) {
// Calculate chunk size based on n (log2(n))
long chunkSize = n.bitLength();
int byteChunkSize = (int) Math.floor((double) chunkSize / 8);
while (dis.available() > 0) {
int encryptedLength = dis.readInt();
byte[] encryptedBuffer = new byte[encryptedLength];
dis.readFully(encryptedBuffer);
BigInteger encryptedChunk = new BigInteger(1, encryptedBuffer);
BigInteger decryptedChunk = encryptedChunk.modPow(d, n);
byte[] decryptedBytes = decryptedChunk.toByteArray();
if (decryptedBytes.length > byteChunkSize) {
fos.write(decryptedBytes, decryptedBytes.length - byteChunkSize, byteChunkSize);
} else {
fos.write(decryptedBytes);
}
}
}
System.out.println("Decryption completed. Decrypted data saved to " + outputFile);
}
public class Utils {
private static BigInteger a = BigInteger.valueOf(6906);
private static BigInteger b = BigInteger.ONE;
private static BigInteger m = BigInteger.TWO.pow(32);
private static BigInteger PREVIOUS_R = BigInteger.ONE;
public static ArrayList<Double> keysTimeGeneration = new ArrayList<>();
public static ArrayList<Double> encryptionTime = new ArrayList<>();
public static ArrayList<Double> decryptionTime = new ArrayList<>();
Hi, I've an application where I want to create a hash of a file, or group of files, and use it to prove that the files are unchanged in the future. Ideally I want to be able to do this in the browser from javascript, to avoid users having to upload files they want to be hashed. Would I be right in thinking that SHA256 would be the best choice to use for this today? I expect it's a painfully obvious question for those who know, I just want to avoid heading down the wrong path as I get going with creating a solution! Thanks
Hello everyone, I'm a uni student and I'm taking one of my first classes about cryptography.
I can't really seem to understand the difference between the traditional method and HPKE mentioned in RFC 9180. I'm not finding much and I'm honestly a bit confused. Do they both use DH? Is the traditional method the static RSA?
Can someone explain it to me or suggesting me some links with reliable info?