Skip to content
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

Fix Incorrect Unsigned Message Error When Using External Keys in decrypt Method #41

Closed
boncossoftware opened this issue May 28, 2024 · 5 comments

Comments

@boncossoftware
Copy link

boncossoftware commented May 28, 2024

Issue Description

Current Behavior

In the decrypt method of the FastOpenPGP struct, the code checks for the SignedBy property to verify if a message is signed. However, this property is not set when the message is signed by keys that are not created with the library, causing issues when attempting to decrypt with a verification key.

The test TestFastOpenPGP_DecryptVerifyEntity currently passes because the public key used to decrypt the message is the same public key of the private key used to decrypt the message. This does not trigger the issue described, as the SignedBy property is correctly set in this specific scenario.

Original Code

func (o *FastOpenPGP) decrypt(reader io.Reader, privateKey, passphrase string, signedEntity *Entity, options *KeyOptions) ([]byte, error) {
    entityList, err := o.readPrivateKeys(privateKey, passphrase)
    if err != nil {
        return nil, fmt.Errorf("privateKey error: %w", err)
    }

    md, err := openpgp.ReadMessage(reader, entityList, nil, generatePacketConfig(options))
    if err != nil {
        return nil, err
    }

    if signedEntity != nil {
        signedEntities, err := o.readPublicKeys(signedEntity.PublicKey)
        if err != nil {
            return nil, fmt.Errorf("publicKey error: %w", err)
        }
        if md.SignatureError != nil {
            return nil, fmt.Errorf("signature error: %w", md.SignatureError)
        }

        if md.SignedBy == nil {
            return nil, errors.New("message is not signed")
        }

        if signedEntities.KeysById(md.SignedByKeyId) == nil {
            return nil, fmt.Errorf("signedKeyId:%d does not belong to the provided signedEntity", md.SignedByKeyId)
        }
    }

    output, err := ioutil.ReadAll(md.UnverifiedBody)
    if err != nil {
        return nil, err
    }
    return output, nil
}

Problem

The md.SignedBy property is not set when the message is signed by keys not created with the library, which results in an error message indicating that the message is not signed, even though it is.

Proposed Fix

Modified Code

func (o *FastOpenPGP) decrypt(reader io.Reader, privateKey, passphrase string, signedEntity *Entity, options *KeyOptions) ([]byte, error) {
    entityList, err := o.readPrivateKeys(privateKey, passphrase)
    if err != nil {
        return nil, fmt.Errorf("privateKey error: %w", err)
    }

    md, err := openpgp.ReadMessage(reader, entityList, nil, generatePacketConfig(options))
    if err != nil {
        return nil, err
    }

    if signedEntity != nil {
        signedEntities, err := o.readPublicKeys(signedEntity.PublicKey)
        if err != nil {
            return nil, fmt.Errorf("publicKey error: %w", err)
        }
        if md.SignatureError != nil {
            return nil, fmt.Errorf("signature error: %w", md.SignatureError)
        }

        if !md.IsSigned {
            return nil, errors.New("message is not signed")
        }

        if signedEntities.KeysById(md.SignedByKeyId) == nil {
            return nil, fmt.Errorf("signedKeyId:%d does not belong to the provided signedEntity", md.SignedByKeyId)
        }
    }

    output, err := ioutil.ReadAll(md.UnverifiedBody)
    if err != nil {
        return nil, err
    }
    return output, nil
}

Explanation

  • Changed the check from md.SignedBy to md.IsSigned to accurately determine if a message is signed.
  • md.IsSigned is used to verify the signed status of the message, which resolves the issue when the message is signed by keys not created with the library.

Impact

This change ensures that the decrypt method correctly identifies signed messages, even if they are signed by external keys, thus preventing false negatives when verifying signatures.

Steps to Reproduce

  1. Sign a message with a key not created by the library and that is not the public key of the private key used to decrypt.
  2. Attempt to decrypt and verify the message using the current decrypt method.
  3. Observe the error indicating that the message is not signed.
  4. Apply the proposed fix and repeat the decryption and verification process.
  5. Observe that the message is now correctly identified as signed.
@jerson
Copy link
Owner

jerson commented May 28, 2024

@boncossoftware thanks for this, going to prepare a PR

@boncossoftware
Copy link
Author

Awesome @jerson, thanks! 🙏 Will the flutter-openpgp package also be updated? That is the package we are currently using that led me to find the issue here.

@jerson
Copy link
Owner

jerson commented May 29, 2024

yeah, is available in https://pub.dev/packages/openpgp/versions/3.8.1, take a look

@boncossoftware
Copy link
Author

Ok great man. Thanks again!

@jerson
Copy link
Owner

jerson commented May 29, 2024

closing this, feel free to reopen if needed

@jerson jerson closed this as completed May 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants