iOS: CryptographicException



  • I've finished testing my app with subscription on Android with many questions on this forum as you know... it's perfectly working. And it's iOS time.

    Next issue occurs on app start. Please, help me. What is the issue?

    Environment:

    • Unity IAP 1.23.5 (because 2.0 has bugs as I know)
    • Unity 2019.4.10
    • SIS 4.3.5
    • iOS 14.0.1
    • The Only IAP: Auto-Renewable Subscription with server validation
    2020-10-14 10:43:15.893407+0300 app[5622:2012007] UnityIAP: Received 1 products
    2020-10-14 10:43:15.900585+0300 app [5622:2012007] UnityIAP: No App Receipt found
    2020-10-14 10:43:15.918698+0300 app [5622:2010201] UnityIAP: No App Receipt found
    Uploading Crash Report
    CryptographicException: Bad PKCS7 padding. Invalid length 0.
      at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (System.Security.Cryptography.PaddingMode padding, System.Int32 length, System.Int32 position) [0x00000] in <00000000000000000000000000000000>:0 
      at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, System.Int32 inputOffset, System.Int32 inputCount) [0x00000] in <00000000000000000000000000000000>:0 
      at SIS.DBManager.Decrypt (System.String toDecrypt) [0x00000] in <00000000000000000000000000000000>:0 
      at SIS.ReceiptValidatorServer.Validate (UnityEngine.Purchasing.Product p) [0x00000] in <00000000000000000000000000000000>:0 
      at SIS.IAPManager.OnInitialized (UnityEngine.Purchasing.IStoreController ctrl, UnityEngine.Purchasing.IExtensionProvider ext) [0x00000] in <00000000000000000000000000000000>:0 
      at UnityEngine.Purchasing.PurchasingManager.CheckForInitialization () [0x00000] in <00000000000000000000000000000000>:0 
      at UnityEngine.Purchasing.PurchasingManager.OnProductsRetrieved (System.Collections.Generic.List`1[T] products) [0x00000] in <00000000000000000000000000000000>:0 
      at UnityEngine.Purchasing.AppleStoreImpl.OnProductsRetrieved (System.String json) [0x00000] in <00000000000000000000000000000000>:0 
      at System.Action.Invoke () [0x00000] in <00000000000000000000000000000000>:0 
      at UnityEngine.Purchasing.Extension.UnityUtil.Update () [0x00000] in <00000000000000000000000000000000>:0
    


  • Great to hear we can check off Android builds!

    CryptographicException: Bad PKCS7 padding. Invalid length 0.
    at SIS.DBManager.Decrypt

    You've enabled encryption and the DBManager is trying to decrypt the local receipt on initialization. Several things can go wrong with this, all resulting in the same message above:

    • there is no receipt. Maybe you have purchased a product before for testing, but enabled validation OnStart later. No receipt is saved in that case
    • you have a local receipt, but enabled encryption later. The DBManager is now trying to decrypt a non-encrypted file
    • you have a local receipt, but it was saved with a different encryption key. The DBManager is therefore not able to decrypt it

    Clear the database on the device (there is a button in the AllSelection scene for this) and start with a new testing state, potentially removing and redeploying the app. Check your encryption key.



  • As on Android, on iOS I delete the App from device to completely clear the cache before testing.

    "there is no receipt. Maybe you have purchased a product before for testing, but enabled validation OnStart later. No receipt is saved in that case"

    No, I have no purchase before. This is 1st build on iOS with IAP.

    "you have a local receipt, but enabled encryption later. The DBManager is now trying to decrypt a non-encrypted file"

    As follows from the previous answer - No.
    I don't remember that encryption was on or off for previous build a few months ago, but 1. IAP was absent in old build. 2. Now I Delete the App from Device for current testing.

    "you have a local receipt, but it was saved with a different encryption key. The DBManager is therefore not able to decrypt it"

    as you understand - no.

    Any suggestions?



  • Try without encryption.

    If it works, delete cache and remove the app, then enable encryption again. If it fails with the same message I will try to reproduce it.



  • Delete App.
    Turn off Encryption.
    Without Encryption there is no such error.
    Next, Delete App.
    Turn on Encryption.
    Error is here.

    P.S. What the goal of separate "Delete Cache"? because all data are deleting alongside app deleting.



  • I always recommend to delete the cache manually, since there are several occurences of PlayerPrefs persisting app installs. Although most of them are on Android. E.g.

    https://forum.unity.com/threads/playerprefs-persist-on-fresh-install.720509/
    https://stackoverflow.com/questions/41820790/playerprefs-are-present-after-uninstalling-the-app-developed-with-unity

    In the DBManager script, GetReceipt method line 327, where it says

    if (instance.encrypt)
    

    does replacing that with the following code check fix it?

    if (!string.IsNullOrEmpty(data) && instance.encrypt)
    


  • @Baroni the exception itself has gone. Thanks.
    I will keep you posted if testing will show anything else on the encryption side.



  • It seems that your fix solves one more issue.

    When I Clicked the button to subscribe then Purchase Dialog is open, next I click cancel & this cancelling causes errors, so I could not get answer with IAPManager.purchaseFailedEvent.

    So After your fix I CAN get the answer here, but the next message is still showing on console:

    <SKPaymentQueue: 0x282156e10>: Payment completed with error: Error Domain=ASDErrorDomain Code=907 "Unhandled exception" UserInfo={NSUnderlyingError=0x282f45020 {Error Domain=AMSErrorDomain Code=6 "Payment Sheet Failed" UserInfo={NSLocalizedDescription=Payment Sheet Failed, NSLocalizedFailureReason=Payment sheet cancelled}}, NSLocalizedFailureReason=An unknown error occurred, NSLocalizedDescription=Unhandled exception}



  • @andrewio said in iOS: CryptographicException:

    It seems that your fix solves one more issue.

    The DBManager.GetReceipt method is actually not called anywhere outside the ReceiptValidatorServer script, so this does not seem to be related. Thanks for reporting back though!


Log in to reply