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

So service allows to create signing for manifest.json of pkpass file. But how the application (e.g. Android app) can verify the signing against manifest.json? #602

Open
anonym24 opened this issue Jan 15, 2025 · 0 comments

Comments

@anonym24
Copy link

So, I tried to implement verification but with no success for now.
So firstly, I guess I have to use the following Apple certificate - https://developer.apple.com/certificationauthority/AppleWWDRCA.cer

I tried the following sample (JVM/Kotlin):

import java.io.File
import java.nio.file.Files
import java.security.MessageDigest
import java.security.Signature
import java.security.cert.CertificateFactory

fun main() {
    val appleCertificateFile = File("AppleWWDRCA.cer")
    val manifestJsonFile = File("manifest.json") // from .pkpass file
    val signatureFile = File("signature") // from .pkpass file

    println(
        verifyManifestSignature(
            manifestJsonFile = manifestJsonFile,
            signatureFile = signatureFile,
            certificateFile = appleCertificateFile
        )
    )
}

fun verifyManifestSignature(
    manifestJsonFile: File,
    signatureFile: File,
    certificateFile: File
): Boolean {
    // Step 1: Read the content of manifest.json
    val manifestBytes = manifestJsonFile.readBytes()

    // Step 2: Compute the SHA-256 hash of manifest.json
    val messageDigest = MessageDigest.getInstance("SHA-256")
    val computedHash = messageDigest.digest(manifestBytes)

    println("computedHash ${computedHash.joinToString("") { "%02x".format(it) }}")

    // Step 3: Extract the signature
    val signatureBytes = signatureFile.readBytes()

    // Step 4: Load the public key from the certificate
    val certificateFactory = CertificateFactory.getInstance("X.509")
    val certInputStream = Files.newInputStream(certificateFile.toPath())
    val certificate = certificateFactory.generateCertificate(certInputStream)
    val publicKey = certificate.publicKey

    // Step 5: Verify the signature using the public key
    val signature = Signature.getInstance("SHA256withRSA")
    signature.initVerify(publicKey)
    signature.update(computedHash)

    // Verify the signature against the data (manifest.json)
    val isVerified = signature.verify(signatureBytes)
    return isVerified
}

But I get the error:

Exception in thread "main" java.security.SignatureException: Bad signature length: got 3347 but was expecting 256
	at java.base/sun.security.rsa.RSASignature.engineVerify(RSASignature.java:215)
	at java.base/java.security.Signature$Delegate.engineVerify(Signature.java:1435)
	at java.base/java.security.Signature.verify(Signature.java:789)
	at PassSignatureKt.verifyManifestSignature(PassSignature.kt:50)
	at PassSignatureKt.main(PassSignature.kt:13)
	at PassSignatureKt.main(PassSignature.kt)

I haven't really worked with the certificates, so what's the correct way to verify all of it?

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