I want to be able to verify the authenticity of a QR code text without internet connection.

Let's say I have a peanut butter store, and I have an online store too. After purchasing at my online store the customer will be given a QR code. They print that QR code and bring it to my actual store, which doesn't have internet connection, and by scanning the QR code with my mobile app I will give them the amount they have purchased.

The QR code plain text will be something like : "John, Doe, 3 jars". Upon scanning this I will give John Doe 3 jars of peanut butter.

Now as far as I know the conventional method for this is to sign the message. But that adds a lot of overhead because I will have to generate the QR code for plaintext+signature. QR codes size is very limited and my messages are very short. So any performance consideration about hashing the message and encrypting that hash are of no importance. While ciphertext size is very important.

So I was thinking, is there any security flaw if I just encrypt the message instead of signing it? If I can decrypt the message in my offline store it means it has really come from my online store and that it has not been tampered with. This way I will avoid the size overhead of signatures, since my messages are not much longer than an SHA-256 hash themselves.

Here's the steps that will be performed:

In online store's web application:

  • create a text message that says a certain customer has purchased a certain amount of peanut butter
  • encrypt the message with my private/public key
  • convert to base64 and generate QR code

In actual store:

  • scan QR code and base64 decode
  • decrypt the message with my public/private key
  • if I'm able to decrypt the message it means the message is authentic and I will give the customer the amount of peanut butter specified in the QR code

Currently I've been able to successfully perform these steps with ECIES encryption in Java. I was just wondering if this is secure. I chose ECIES because after some research I figured it produces small sized cipher text. And I'm using "secp192r1" keys as a compromise between ciphertext size and key security.

Also I want the encryption to be asymmetric, because for security reasons I don't want to hard code my symmetric key into the mobile app.

This is not an actual work project, but it's something that's always been on my mind and I want to be able to do this in a real project if need arises.

  • $\begingroup$ The only time when encryption authenticates a message is in "authenticated encryption", which is symmetric. For the authentication to be asymmetric, you have to use a digital signature scheme. $\endgroup$
    – DannyNiu
    Apr 21, 2020 at 7:48
  • $\begingroup$ When using encryption for the mobile device, don't you have to hard-code the private decryption key into the app? The only to not hard-code a secret key into the app is to use an asymmetric signature. Did you also consider how to prevent a customer from coming in multiple times with the same code to get multiple deliveries of what they ordered? $\endgroup$
    – SEJPM
    Apr 21, 2020 at 7:58
  • $\begingroup$ @DannyNiu I don't understand why. Isn't a digital signature an encrypted hash of the message? It's ultimately the same thing as encryption isn't it? $\endgroup$
    – Pouria
    Apr 21, 2020 at 8:03
  • $\begingroup$ @SEJPM One key will be hard-coded into the app, but that will be like a public key. Even if someone can extract it what will they be able to do with it? My key with which I encrypt messages is on my server. About coming in multiple times, yes I will keep a database of processed purchases in the app. $\endgroup$
    – Pouria
    Apr 21, 2020 at 8:05
  • $\begingroup$ @Pouria, Sure you can think digital signature as encrypted hash, but that encryption has to be performed by the private key; ECIES encrypts data using the public key, which is available to everyone! $\endgroup$
    – DannyNiu
    Apr 21, 2020 at 8:16

2 Answers 2


Since everyone's answers were in the comments and I want to mark this as answered I'm answering my own question based on what I learnt from your comments and further research:

The answer is you simply can not encrypt with a private key. Encrypting with private keys is only possible in theoretical scenarios and only with RSA keys.

And if you try to encrypt with the public key, then you will have to share your private key. And no, they are not interchangeable, most importantly if someone has the private key they can derive both keys from it.

So the only possible way is to sign the message.

This answer could be useful for people like me who have read simplistic online articles about how cryptography works and were led to believe that public and private keys are interchangeable.

  • $\begingroup$ In early versions of the most used RSA standard, PKCS#1, they also talk about encryption with a private key. That may not have helped matters. In version 2 they clarified that only the exponentiation function is identical - when it comes to the math formula anyway, the implementation will still differ. You will still find "RSA encryption" if you look in X.509 certificates - even if they are used for signing only. $\endgroup$
    – Maarten Bodewes
    Apr 29, 2020 at 9:19

the conventional method is to sign the message

That's one of two classes of conventional methods to prevent QR-code forgery, and there are several signature schemes. All those known¹ add at least $2b$-bit to the data embedded in the QR-code (even $3b$ bits for most, and all those applicable to very small message), where $b$ is a security parameter in bit (equivalent to a symmetric key size). $b=80$ (thus at least 20 bytes added in the QR-Code) seems a bare minimum for security against determined and powerful adversaries. The advantage of signing is that no secret is necessary to verify a QR-code.

Another class of conventional methods is adding a Message Authentication Code to the message. That adds only $b$ bit in the QR-Code for $2^{-b}$ probability that a forged QR-code is accepted. If trying a QR-code takes 0.001 second to an adversary, $b=40$ (5 bytes added to the QR-Code) already gives some very useful protection (1% chance to forge a QR-code in 4 months of trying). The huge disadvantage is that the MAC's secret key must be used in the verification of the QR-code, and keeping it secret is problematic. Methods include a security IC in the reader, which can also enforce a maximum try rate, allowing to further reduce the MAC size.

If only signature is applicable, appending an RSA signature is almost certainly not the best method, because the overhead is so large (near 128 bytes for 1024-bit RSA, which is no longer recommendable). See this answer for some better suited schemes.

¹ At least, restricting to those believed to give security under chosen plaintext attack.

  • $\begingroup$ Thanks for the extra info on other methods. I'm already using a 192-bit EC key which gives me an acceptably small sized signature. $\endgroup$
    – Pouria
    Apr 22, 2020 at 8:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.