Skip to content

Commit

Permalink
Merge branch 'unify-validation-and-signature-creation' into various-i…
Browse files Browse the repository at this point in the history
…mprovements
  • Loading branch information
ueman committed Sep 20, 2024
2 parents 2059946 + 132e669 commit 0e8eca6
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 14 deletions.
14 changes: 14 additions & 0 deletions passkit/lib/src/certificate_extension.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import 'package:collection/collection.dart';
import 'package:pkcs7/pkcs7.dart';

extension CertX on X509 {
/// Matches the pass type identifer for PkPass and the merchant identifier for
/// orders
String? get identifier =>
subject.firstWhereOrNull((it) => it.key.name == 'UID')?.value as String?;

/// Matches the team identifier
String? get teamIdentifier => subject
.firstWhereOrNull((it) => it.key.name == 'organizationalUnitName')
?.value as String?;
}
4 changes: 2 additions & 2 deletions passkit/lib/src/order/pk_order.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ class PkOrder {
});

/// Parses bytes to a [PkOrder] instance.
/// Setting [skipVerification] to true disables any checksum or signature
/// verification and validation.
/// Setting [skipChecksumVerification] and [skipSignatureVerification] to true
/// disables checksum or signature verification and validation.
// TODO(ueman): Provide an async method for this.
static PkOrder fromBytes(
final Uint8List bytes, {
Expand Down
5 changes: 4 additions & 1 deletion passkit/lib/src/pkpass/pkpass.dart
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,10 @@ class PkPass {
final signature = writeSignature(
certificatePem,
privateKeyPem,
Uint8List.fromList(manifestFile.content as List<int>),
manifestFile.binaryContent,
pass.passTypeIdentifier,
pass.teamIdentifier,
true,
);

final signatureFile = ArchiveFile(
Expand Down
14 changes: 3 additions & 11 deletions passkit/lib/src/signature_verification.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:typed_data';
import 'package:collection/collection.dart';
import 'package:crypto/crypto.dart';
import 'package:passkit/src/apple_wwdr_certificate.dart';
import 'package:passkit/src/certificate_extension.dart';
import 'package:passkit/src/pkpass/exceptions.dart';
import 'package:pkcs7/pkcs7.dart';

Expand Down Expand Up @@ -52,22 +53,13 @@ bool verifySignature({
// Set the serialNumber key to the unique serial number for that identifier.

final signerInfo = pkcs7.verify([wwdrG4]);
// final algo = signerInfo.getDigest(signerInfo.digestAlgorithm); Calculate hash based on the algo?
return signerInfo.listEquality(manifestHash, signerInfo.messageDigest!);
}

bool Function(X509) _verifier(String teamIdentifier, String identifier) {
return (X509 x509) {
final identifierMatches =
x509.subject.firstWhereOrNull((it) => it.key.name == 'UID')?.value ==
identifier;

final teamIdentifierMatches = x509.subject
.firstWhereOrNull(
(it) => it.key.name == 'organizationalUnitName',
)
?.value ==
teamIdentifier;
final identifierMatches = x509.identifier == identifier;
final teamIdentifierMatches = x509.teamIdentifier == teamIdentifier;

return identifierMatches && teamIdentifierMatches;
};
Expand Down
42 changes: 42 additions & 0 deletions passkit/lib/src/write_signature.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:passkit/src/apple_wwdr_certificate.dart';
import 'package:passkit/src/certificate_extension.dart';
import 'package:passkit/src/pkpass/exceptions.dart';
import 'package:pkcs7/pkcs7.dart';
import 'package:pointycastle/pointycastle.dart';

Expand All @@ -19,8 +21,17 @@ Uint8List writeSignature(
String certificatePem,
String privateKeyPem,
Uint8List manifestBytes,
String identifier,
String teamIdentifier,
bool isPkPass,
) {
final issuer = X509.fromPem(certificatePem);
_ensureCertificateMatchesPass(
issuer,
identifier,
teamIdentifier,
isPkPass,
);

final pkcs7Builder = Pkcs7Builder();

Expand All @@ -47,3 +58,34 @@ Uint8List writeSignature(
final pkcs7 = pkcs7Builder.build();
return pkcs7.der;
}

void _ensureCertificateMatchesPass(
X509 issuer,
String identifier,
String teamIdentifier,
bool isPkPass,
) {
final identifierMatches = issuer.identifier == identifier;
final teamIdentifierMatches = issuer.teamIdentifier == teamIdentifier;

if (identifierMatches) {
if (isPkPass) {
throw Exception(
"PkPass.pass.passTypeIdentifier doesn't match the certificate Pass Type ID",
);
} else {
// TODO(any): Write a proper exception for orders
throw SignatureMismatchException();
}
}
if (teamIdentifierMatches) {
if (isPkPass) {
throw Exception(
"PkPass.pass.teamIdentifier doesn't match the certificate team ID",
);
} else {
// TODO(any): Write a proper exception for orders
throw SignatureMismatchException();
}
}
}

0 comments on commit 0e8eca6

Please sign in to comment.