Reputation: 12293
So signature in .pkpass file (zip) is used for validation of .pkpass's manifest.json file.
Somehow I need to verify it (I guess using the following Apple certificate https://developer.apple.com/certificationauthority/AppleWWDRCA.cer)
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 certificates, so what's the correct way to verify all of it?
Update
I have found the following example in C# but it's hard for me to rewritten it to Java/Kotlin version:
https://github.com/tomasmcguinness/pkpassvalidator/blob/master/PassValidator.Validator/Validator.cs
Upvotes: 0
Views: 36