How to supply tag information with GCM encrypted data?

As per the sandbox documentation, we need to encrypt health data using AES-GCM cipher during data push. We are using aes-256-gcm cipher however GCM ciphers generate tag authentication data and this data is required to decrypt the encrypted text. Typically, IV, cipher and tag data is required to decrypt. Both parties will be able to produce same IV and cipher is already decided. We are not sure how the tag is going to be exchanged with the other party.

You can refer to https://www.php.net/manual/en/function.openssl-encrypt.php . Although $tag parameter is option, it is mandatory in case of GCM and it is required and will be needed to use in openssl_decrypt .

We have tried to figure this out with Github gist provided for Java & C# but were unable to figure that out. Are we missing something here?

1 Like

we are using the DHKE, encryption is AES-256 but you need to use the right curve and algo, and pass the requester nonce as well.
Sandbox has documentation on the process requester->sender->requester here, which I am assuming you already saw.
Have you tried running the examples (in gist) first?
@dheerajp @leelanakka

Hi Any update here? We are stuck in the integration due to above clarity needed. There is not detail related to tag in the documentation provided. @angshuonline

Hi @bhaskar.dabhi,

please follow the following gist for encryption and decryption https://gist.github.com/Nexengineer/23589d0e8eeab0ad0f50cffdf4be6bca

Hi,

The gist provided are implementation in C# and Java. We use neither.

For reference, we have done this implementation in PHP. This is the link to the gist: https://gist.github.com/ksg91/0a01b35693b7cc8157984973767937fc

As you can see, we are using a global variable called $tag . This is passed by reference to openssl_encrypt function and it is filled by function with authentication tag. You need this authentication tag to decrypt the data correctly and in PHP, it is a required parameter. You can also check the the details for this here: https://en.wikipedia.org/wiki/Galois/Counter_Mode

Authentication tag needs to be supplied separately so that the other party can decrypt it correctly.

Can someone please help us with this? Can you point out what we are doing wrong here or provide an explanation with is programming language agnostic? The gists in Java & C# are not really helping.

Hi @kishan.gor,

We are checking this. We will get back to you.

Thanks

1 Like

Hi Any update? @dheerajp

Hi @kishan.gor, @bhaskar.dabhi,

We have found related topic on StackOverflow https://stackoverflow.com/questions/43812874/aes-256-bit-gcm-encryption-on-php-side-and-decryption-on-java-side. Please follow this. However we don’t have and sample for PHP encryption/decryption.

Regards

Hi Dheeraj,

Thanks for the reference. However, that didn’t work for us. Do you know if someone can provide us the implementation of this in official openssl command line utility at least?

So I just want to clarity that we are able to get this encryption working in PHP, just that GCM cipher is an authenticated cipher. It needs auth_tag generated during encryption along with same IV to decrypt the data correctly. This is defined here: https://en.wikipedia.org/wiki/Galois/Counter_Mode

NDHM has already defined way for IV exchange on the basis of XOR of random nouces. However, there is no information no exchange of auth tag.

I am no expert on cryptography, but it seems that the sample implementation in Java or C# is bypassing auth requirement for GCM and hence able to get it working. However, PHP & openssl doesn’t allow bypassing that. Can someone who has experience in this can confirm if that’s correct? Doesn’t it mean that the official implementation is using GCM cipher incorrectly and insecurely? I may be wrong so answer from someone experience in this would be helpful.

Hi @kishan.gor

We did some research by following your gist in PHP. Please find below points which we were able to figure out:

  • As mentioned in earlier references, the $tag variable needs to be appended at the end of the encrypted text. The java implementation will search for it as the last 16 digits of the encrypted text.
    Also the option OPENSSL_RAW_DATA needs to be passed while encrypting and the combination (encrypted text + tag) need to be encoded separately.
    Please refer to this answer on SO, it explains how the PHP encryption will be decrypted in Java. It is sending even version and iv as part of encrypted text(appended in the starting), which can be ignored. The version is not required and iv is acquired as last 12 bytes of the nonce XOR.

  • Also a slight correction for the $iv calculation in the PHP side. The last 12 bits of the XOR should be used as IV. In the PHP $iv = substr($xorOfRandoms, 0, -12); is used which would give all but last 12 characters.

  • The encryption is done using the Elliptic-curve Diffie–Hellman(ECDH) key agreement protocol. While doing some research we found out that the openssl library for PHP does not support this algorithm(Reference https://stackoverflow.com/a/56227222/3423097). However there might be other libraries or tweaks which can get it working for PHP which we have not researched.

We hope this helps.
CC: @sukreet @angshuonline @dheerajp @leelanakka @Gayatrij @Mounica

1 Like

Hi @mdubey this helped a lot. We generated our Private public key and we use their Java code for decryption the we face following issues:

Exception in thread "main" java.lang.IllegalArgumentException: Scalar is not in the interval [1, n - 1]
        at org.bouncycastle.crypto.params.ECDomainParameters.validatePrivateScalar(Unknown Source)
        at org.bouncycastle.crypto.params.ECPrivateKeyParameters.<init>(Unknown Source)
        at org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.generatePrivateKeyParameter(Unknown Source)
        at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyAgreementSpi.initFromKey(Unknown Source)
        at org.bouncycastle.jcajce.provider.asymmetric.ec.KeyAgreementSpi.engineInit(Unknown Source)
        at javax.crypto.KeyAgreement.init(KeyAgreement.java:467)
        at javax.crypto.KeyAgreement.init(KeyAgreement.java:441)
        at main.doECDH(main.java:218)
        at main.decrypt(main.java:139)
        at main.main(main.java:90)

@mdubey @dheerajp @Mounica

Check following snippet:

https://paste.laravel.io/5d9b67b8-6f31-41a8-ae3e-2479516f38c2

Hi @bhaskar.dabhi,
I can see both encryption as well as decryption code in that snippet. Are you implementing both HIU as well as HIP?

hi @kishan.gor
I am trying this reference to encryption and decryption
i am running this programed from my local server, program is working for given test data in the file. but if i am sending the receiverPublicKey and randomKeyReceiver values with the values i am getting from NDHM then i am not getting the decrypted value.

Please guide me anything i am doing wrong in this…

We are implementing for the HIP right now.

Hi @srinivasarao, we are still trying to figure it out on how to get it working for the implementation provided by NDHM but so far no luck. It seems Java has different way of handling the encrypted data and the suggestions provided so by various people have not worked.

Hello @bhaskar.dabhi, @kishan.gor, @srinivasarao

We have not been able to get much info on PHP yet. However couple of pointers might help you. Since in the post earlier we mentioned, it is likely that the openssl library for PHP does not support the ECDH algorithm for key generation. However, this is the standard we are supposed to use while generating/loading the key for data exchange.

We are suspecting that the Java KeyFactory engine is trying to load the keys provided as expected by ECDH algorithm and it is failing because it is not a valid one. Could you please give a try with libraries which are capable of supporting ECDH Keys in PHP.

A few top results from search are coming as below, however if there are any better libraries in PHP, please go ahead with that.


Thanks

Hi Everyone,

Is there any repo for Nodejs for encryption and decryption?