-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Encrypt decrypt #2130
base: master
Are you sure you want to change the base?
Encrypt decrypt #2130
Conversation
Pull Request Test Coverage Report for Build 8143981554Details
💛 - Coveralls |
Nice this is the commit that removes it: I think we might get more context as to why it was removed. The function that was used to type alias the functions removed here does not have it either: |
@Chinwendu20 The context as to why it was removed is found here: #1880 (comment). |
@guggero - is it possible to get a review of this PR please? I have a project that we recently upgraded to the latest version of the library and ended up copying over this code. Would be great to have this functionality available in the library again. |
I'm super busy right now. You're welcome to add a review yourself, since you seem to need the code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the PR and sharing the reference doc, it helped me review. Left a question and other comments. Also is there a reason why this b9f98b6 is a separate commit? Can it not be merged with previous?
Commits are usually in the form: package name: commit message
. Here is the guideline:
https://github.com/lightningnetwork/lnd/blob/master/docs/code_contribution_guidelines.md#ideal-git-commit-structure
I think maybe these guidelines should be included in this repo as well.
Also I am not entirely sure why this should be here (same withe the sharedSecrets function), I do not think we use them any where, maybe there is a reason it was left for users to create themselves, it is not even in the decred
secp256k1 package itself. Maybe it would be more appropriate to have that there? then we can have encrypt functions for AES-256, AES-128, etc.
Ohh I see btcec was created as a standalone golang bitcoin as opposed to decred that is for a different ecosystem. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could be wrong but I think the point of the issue that birthed this PR is to bring back the Encrypt and Decrypt function here back here:
Left comments in the Resolved thread as well. Maybe hold on, on resolving comment for now.
ecdhKey := GenerateSharedSecret(ephemeral, pubKey) | ||
hashedSecret := sha256.Sum256(ecdhKey) | ||
encryptionKey := hashedSecret[:16] | ||
block, err := aes.NewCipher(encryptionKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like you sliced the shared secret to 16 bytes here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes for compatibility with AES-128-GCM encryption
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh thought you said AES-256-GCM here: a2245a6#r1570762508 but looks like the comment has been updated.
} | ||
|
||
gcm, err := cipher.NewGCMWithNonceSize(block, 16) | ||
if err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to understand why it has to be a nonce size of 16 instead of the default 12
@@ -22,14 +23,19 @@ func GenerateSharedSecret(privkey *PrivateKey, pubkey *PublicKey) []byte { | |||
|
|||
// Encrypt encrypts data for the target public key using AES-128-GCM | |||
func Encrypt(pubKey *PublicKey, msg []byte) ([]byte, error) { | |||
var pt bytes.Buffer | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You want to copy the cipher text into a different variable?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
var pt bytes.Buffer
is used to accumulate the encrypted data in a buffer, which is then returned as a single byte slice at the end of the function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not return the cipher text itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i didnt return the ciphertext itself because i need some details in the decrypt function. the tag (and other parameters like nonce etc) are appended to the ciphertext in the encrypt function and in the decrypt function the tag is separated from the ciphertext to verify authenticity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the tag is in the cipher text already
Is there a reason that you did not just do this:
nonce := make([]byte, aead.NonceSize())
ciphertext := make([]byte, 4+len(ephemeralPubKey))
binary.LittleEndian.PutUint32(ciphertext, uint32(len(ephemeralPubKey)))
copy(ciphertext[4:], ephemeralPubKey)
ciphertext = aead.Seal(ciphertext, nonce, plaintext, ephemeralPubKey)
Gotten from here: https://pkg.go.dev/github.com/decred/dcrd/dcrec/secp256k1/v4#section-readme
No need for the intermediary pt bytes in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both approaches are valid. I used a buffer as it automatically grows and shrinks as needed, reducing manual memory management.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO, I do not think the buffer is needed at all when the cipher text can just be returned directly unless there is need to copy the cipher text into a different variable. if not maybe we should not use extra space.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i didnt return the ciphertext itself because i need some details in the decrypt function. the tag (and other parameters like nonce etc) are appended to the ciphertext in the encrypt function and in the decrypt function the tag is separated from the ciphertext to verify authenticity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nonce := make([]byte, aead.NonceSize())
ciphertext := make([]byte, 4+len(ephemeralPubKey))
binary.LittleEndian.PutUint32(ciphertext, uint32(len(ephemeralPubKey)))
copy(ciphertext[4:], ephemeralPubKey)
ciphertext = aead.Seal(ciphertext, nonce, plaintext, ephemeralPubKey)
If you write it this way would you still need the intermediary buffer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/Chinwendu20/btcd/blob/317cdc7a2a2e25f5d0251decaebccc9da2b2fb66/btcec/ciphering.go#L26-L55
This is what I mean, no need for the buffer or any intermediate?
btcec/ciphering.go
Outdated
@@ -62,3 +63,44 @@ func Encrypt(pubKey *PublicKey, msg []byte) ([]byte, error) { | |||
|
|||
return pt.Bytes(), nil | |||
} | |||
|
|||
// Decrypt decrypts a passed message with a receiver private key, returns plaintext or decryption error |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
format: Line length
Edit:
80 cols limit
// Decrypt decrypts a passed message with a receiver private key, returns plaintext or decryption error | ||
func Decrypt(privkey *PrivateKey, msg []byte) ([]byte, error) { | ||
// Message cannot be less than length of public key (65) + nonce (16) + tag (16) | ||
if len(msg) <= (1 + 32 + 32 + 16 + 16) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the length of public key compressed 33 bytes? Maybe make comments clearer on how the number came about, what does 1 represent here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An uncompressed public key in Elliptic Curve Cryptography (ECC) consists of:
1 byte for the curve type
32 bytes for the X coordinate
32 bytes for the Y coordinate
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An uncompressed public key in Elliptic Curve Cryptography (ECC) consists of: 1 byte for the curve type 32 bytes for the X coordinate 32 bytes for the Y coordinate
Was actually referring to serialized compressed public key which is what was written into the bytes during the encryption.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its actually an uncompressed public key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that is true, I can see that an uncompressed public key was used in the encrypt function. Maybe this code would be clearer this way:
if len(msg) <= (1 + 32 + 32 + 16 + 16) { | |
// Message cannot be less than the size of an | |
// uncompressed public key (65 bytes) + nonce (16 bytes) | |
// + tag (16 bytes) | |
if len(msg) <= (65+ 16 + 16) { |
Or something better
If 1+ 32 + 32 is to be included maybe include where the numbers are from in the comment as well?
I think in general the point of this PR is to bring back the encrypt and decrypt function that was previously in btcec as opposed to writing a new one. Though maybe new encryption and decryption functions could be included as well but not the point of the issue. Others can give their opinion. |
btcec Encrypt / Decrypt used to be available in btcec but wasn't present in btcec/v2. This PR adds it in btcec/v2.
https://pkg.go.dev/github.com/btcsuite/btcd/btcec/v2
Closes #1880