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

Consistently receiving 'cannot verify signature' #1

Open
ipsi-apant opened this issue Mar 14, 2024 · 0 comments
Open

Consistently receiving 'cannot verify signature' #1

ipsi-apant opened this issue Mar 14, 2024 · 0 comments

Comments

@ipsi-apant
Copy link

Describe the bug:
https://developers.google.com/pay/api/web/guides/resources/payment-data-cryptography#using-tink

We are doing the steps mentioned in this document but consistently receiving error for signature verification. Please advise.

Error: 'cannot verify signature'

What was the expected behavior?

Expectation is the encrypted payload signature should be verified and able to unseal using the private key.
However, it fails during signature verification.

How can we reproduce the bug?

https://developers.google.com/pay/api/web/guides/resources/payment-data-cryptography#example

You will need to generate an encrypted message using the merchant id.

Sample request

{
  "apiVersion": 2,
  "apiVersionMinor": 0,
  "allowedPaymentMethods": [
    {
      "type": "CARD",
      "parameters": {
        "allowedAuthMethods": ["PAN_ONLY", "CRYPTOGRAM_3DS"],
        "allowedCardNetworks": ["VISA", "MASTERCARD"]
      },
      "tokenizationSpecification": {
        "type": "PAYMENT_GATEWAY",
        "parameters": {
          "gateway": "we-are-using-gateway-name",
          "gatewayMerchantId": "test"
        }
      }
    }
  ],
  "merchantInfo": {
    "merchantId": "test",
    "merchantName": "Example Merchant"
  },
  "transactionInfo": {
    "totalPriceStatus": "ESTIMATED",
    "totalPrice": 10,
    "currencyCode": "AUD"
  }
}

Unit test

@Test
  public void testUnseal() throws Exception {
    
    // created using Google Pay API via GPAY button in JS
    // The value for "tokenizationData.token" is similar to the value in following example
    // https://developers.google.com/pay/api/web/guides/resources/payment-data-cryptography#example
    String encryptedMessage = "..."; 

    PaymentMethodTokenRecipient recipient =
        new PaymentMethodTokenRecipient.Builder()
            .protocolVersion("ECv2")
            .fetchSenderVerifyingKeysWith(GooglePaymentsPublicKeysManager.INSTANCE_TEST)
            .recipientId("test") // encryptedMessage created using this merchant id
            .addRecipientPrivateKey(googlePayPrivateKey)
            .build();

    String decryptedMessage = recipient.unseal(encryptedMessage); // Fails here

    log.info("Decrypted Message: {}", decryptedMessage);
  }

Do you have any debugging information?

Error stack trace

java.security.GeneralSecurityException: cannot verify signature
	at com.google.crypto.tink.apps.paymentmethodtoken.PaymentMethodTokenRecipient.verify(PaymentMethodTokenRecipient.java:471)
	at com.google.crypto.tink.apps.paymentmethodtoken.PaymentMethodTokenRecipient.verifyECV2(PaymentMethodTokenRecipient.java:409)
	at com.google.crypto.tink.apps.paymentmethodtoken.PaymentMethodTokenRecipient.unsealECV2(PaymentMethodTokenRecipient.java:375)
	at com.google.crypto.tink.apps.paymentmethodtoken.PaymentMethodTokenRecipient.unseal(PaymentMethodTokenRecipient.java:352)

What version of Tink are you using?

1.10.0

Can you tell us more about your development environment?

JDK 21
Springboot 3.2.2
Gradle wrapper 8.6

Private keys stored in AWS secrets manager which are fetched using spring.config.import

The root public key auto refresh instance is being evaluated in spring configuration during application bootup

@Configuration
@Slf4j
public class AppConfigs {

  @Bean
  public GooglePaymentsPublicKeysManager googlePaymentsPublicKeysManager(@Value("${spring.profiles.active}") String activeProfile) {
    log.info("Initializing GooglePaymentsPublicKeysManager based on profile: '{}'", activeProfile);

    return Optional.ofNullable(activeProfile)
                   .filter(Constants.PROD_PROFILE::equalsIgnoreCase)
                   .map(prod -> {
                     log.info("Initializing GooglePaymentsPublicKeysManager public key refresh for 'production'");
                     // Refresh the keys in the background for production
                     GooglePaymentsPublicKeysManager.INSTANCE_PRODUCTION.refreshInBackground();
                     return GooglePaymentsPublicKeysManager.INSTANCE_PRODUCTION;
                   })
                   .orElseGet(() -> {
                     log.info("Initializing GooglePaymentsPublicKeysManager public key refresh for 'test'");
                     // Refresh the keys in the background for test
                     GooglePaymentsPublicKeysManager.INSTANCE_TEST.refreshInBackground();
                     return GooglePaymentsPublicKeysManager.INSTANCE_TEST;
                   });
  }
}

Is there anything else you'd like to add?

A bit stuck at the moment as we are following the steps mentioned on the document.

References

@morambro morambro transferred this issue from tink-crypto/tink-java Mar 14, 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

1 participant