最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ios - Apple wallet in-app push provisioning issue - Stack Overflow

programmeradmin2浏览0评论

I need some help on this issue. I'm trying to provision a digital card to be added to Apple wallet. I get the encrypted activation data from a third party. My job is to encrypt the card details using KDF function. The encryption process goes smooth, I don't see any errors in it, but when I try to actually provision a card, Apple is not able to add it to Wallet. There is no error reported. I reached out to Apple but they have been less than helpful. This is what is happening

  • Extract the apple public key from the leaf certificate:
var certParser = new X509CertificateParser();
                var cert = certParser.ReadCertificate(certificateBytes);

                // Extract the public key
                var publicKey = cert.GetPublicKey();

                // Ensure it's an EC key (which it should be for Apple Wallet)
                if (publicKey is ECPublicKeyParameters ecPublicKey)
                {
                    // Encode the public key in the format expected by your encryption method
                    var encodedPublicKey = SubjectPublicKeyInfoEncoder.GetEncoded(ecPublicKey);
                    return Convert.ToBase64String(encodedPublicKey);
                }
  • Create Card details
var cardDetails = new CardDetails
                {
                    PrimaryAccountNumber = "*************",
                    Expiration = "03/27",
                    Name = Settings.Account?.CustName,
                    Nonce = Convert.ToHexString(nonce.ToArray()),
                    NonceSignature = Convert.ToHexString(nonceSignature.ToArray()),
                };
  • Decode and parse Apple's public key
// 1. Decode and parse Apple's public key
            var applePublicKeyBytes = Convert.FromBase64String(applePublicKeyBase64);
            var applePublicKey = PublicKeyFactory.CreateKey(applePublicKeyBytes);
            var ecPublicKey = (ECPublicKeyParameters)applePublicKey;
// 2. Generate an ephemeral key pair using the same curve as Apple's key
            var curveParameters = ecPublicKey.Parameters;
            var curveName = GetCurveName(ecPublicKey);
//2.1 Generate ephemeral key pair
            var keyGen = new ECKeyPairGenerator();
            keyGen.Init(new ECKeyGenerationParameters(curveParameters, new SecureRandom()));
            var ephemeralKeyPair = keyGen.GenerateKeyPair();
            var ephemeralPrivateKey = (ECPrivateKeyParameters)ephemeralKeyPair.Private;
            var ephemeralPublicKey = (ECPublicKeyParameters)ephemeralKeyPair.Public;

// 3. Perform ECDH key agreement
            var agreement = new ECDHBasicAgreement();
            agreement.Init(ephemeralPrivateKey);
            var sharedSecret = agreement.CalculateAgreement(ecPublicKey);

            // 4. Generate a symmetric key using SHA-256
            var sharedSecretBytes = sharedSecret.ToByteArrayUnsigned();
            var symmetricKey = DeriveSymmetricKey(sharedSecretBytes);

            // 5. Generate a random nonce/IV for AES-GCM
            var nonce = GenerateRandomBytes(AesGcmIvLengthBytes);

            // 6. Prepare the card data for encryption (convert to JSON)
            var cardDataBytes = SerializeCardDetails(cardDetails);

            // 7. Encrypt the card data using AES-GCM
            var encryptionResult = EncryptWithAesGcm(cardDataBytes, symmetricKey, nonce);

            // 8. Encode the ephemeral public key
            var ephemeralPublicKeyEncoded = SubjectPublicKeyInfoEncoder.GetEncoded(ephemeralPublicKey);

            // 9. Create the encrypted data structure
            if (encryptionResult is { Ciphertext: not null, AuthTag: not null })
                return new EncryptedCardData
                {
                    EncryptedData = Convert.ToBase64String(encryptionResult.Ciphertext),
                    EphemeralPublicKey = Convert.ToBase64String(ephemeralPublicKeyEncoded),
                    Tag = Convert.ToBase64String(encryptionResult.AuthTag),
                    Nonce = Convert.ToBase64String(nonce),
                    // The ActivationData field is optional and depends on your implementation needs
                    ActivationData = GenerateActivationData()
                };

//and then finally
// Create the payment pass request to be returned to Apple
                if (encryptedData is { EncryptedData: not null, EphemeralPublicKey: not null })
                {
                    var request = new PKAddPaymentPassRequest
                    {
                        EncryptedPassData = NSData.FromString(encryptedData.EncryptedData, NSStringEncoding.UTF8),
                        ActivationData = string.IsNullOrEmpty(encryptedData.ActivationData) ? null :
                            NSData.FromString(encryptedData.ActivationData, NSStringEncoding.UTF8),
                        EphemeralPublicKey = NSData.FromString(encryptedData.EphemeralPublicKey, NSStringEncoding.UTF8)
                    };

                    // Return the request to Apple via the completion handler
                    handler(request);
                }

When the handler is called, I get this: enter image description here Not sure what is going on.

Any idea what could be happening. I'm provisioned with apple. All entitlements are set and I'm testing it on TestFlight.

I have tried reaching out to apple, reimplementing it about 3 times I think. Looked in to ChatGPT, Grok and Claude. Nothing has worked.

发布评论

评论列表(0)

  1. 暂无评论