优化结构

This commit is contained in:
Yvan
2026-08-27 22:33:43 +08:00
parent 5052835fcb
commit e407d3ac10
86 changed files with 3151 additions and 726 deletions
+65 -16
View File
@@ -4,10 +4,12 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"crypto/x509"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/base64"
"encoding/hex"
"encoding/json"
"math/big"
"testing"
@@ -16,7 +18,8 @@ import (
func TestValidateAppleJWSChain(t *testing.T) {
chain := testAppleCertificateChain(t)
if err := validateAppleJWSChain(testAppleJWS(t, "ES256", chain, time.Now())); err != nil {
jws := testAppleJWS(t, "ES256", chain, time.Now())
if err := validateAppleJWSChainWithRoots(jws, testAppleTrustedRoots(t, chain)); err != nil {
t.Fatalf("validateAppleJWSChain() error = %v", err)
}
}
@@ -25,17 +28,30 @@ func TestValidateAppleJWSChainRejectsUnrelatedLeaf(t *testing.T) {
chain := testAppleCertificateChain(t)
attackerChain := testAppleCertificateChain(t)
chain[0] = attackerChain[0]
if err := validateAppleJWSChain(testAppleJWS(t, "ES256", chain, time.Now())); err == nil {
if err := validateAppleJWSChainWithRoots(testAppleJWS(t, "ES256", chain, time.Now()), testAppleTrustedRoots(t, chain)); err == nil {
t.Fatal("validateAppleJWSChain() accepted a leaf outside the declared chain")
}
}
func TestValidateAppleJWSChainRejectsInvalidSignature(t *testing.T) {
chain := testAppleCertificateChain(t)
jws := testAppleJWS(t, "ES256", chain, time.Now())
header, payload, _, err := splitAppleJWS(jws)
if err != nil {
t.Fatal(err)
}
tampered := header + "." + payload + "." + base64.RawURLEncoding.EncodeToString(make([]byte, 64))
if err = validateAppleJWSChainWithRoots(tampered, testAppleTrustedRoots(t, chain)); err == nil {
t.Fatal("validateAppleJWSChain accepted an invalid ES256 signature")
}
}
func TestValidateAppleJWSChainRejectsUnexpectedAlgorithmAndShape(t *testing.T) {
chain := testAppleCertificateChain(t)
if err := validateAppleJWSChain(testAppleJWS(t, "ES384", chain, time.Now())); err == nil {
if err := validateAppleJWSChainWithRoots(testAppleJWS(t, "ES384", chain, time.Now()), testAppleTrustedRoots(t, chain)); err == nil {
t.Fatal("validateAppleJWSChain() accepted a non-ES256 algorithm")
}
if err := validateAppleJWSChain(testAppleJWS(t, "ES256", chain[:2], time.Now())); err == nil {
if err := validateAppleJWSChainWithRoots(testAppleJWS(t, "ES256", chain[:2], time.Now()), nil); err == nil {
t.Fatal("validateAppleJWSChain() accepted an incomplete x5c chain")
}
}
@@ -43,14 +59,14 @@ func TestValidateAppleJWSChainRejectsUnexpectedAlgorithmAndShape(t *testing.T) {
func TestValidateAppleJWSChainRejectsAdditionalCertificates(t *testing.T) {
chain := testAppleCertificateChain(t)
chain = append(chain, chain[2])
if err := validateAppleJWSChain(testAppleJWS(t, "ES256", chain, time.Now())); err == nil {
if err := validateAppleJWSChainWithRoots(testAppleJWS(t, "ES256", chain, time.Now()), testAppleTrustedRoots(t, chain[:3])); err == nil {
t.Fatal("validateAppleJWSChain() accepted additional x5c certificates")
}
}
func TestValidateAppleJWSChainRejectsNonAppleSigningCertificates(t *testing.T) {
chain := testAppleCertificateChainWithoutAppleExtensions(t)
if err := validateAppleJWSChain(testAppleJWS(t, "ES256", chain, time.Now())); err == nil {
if err := validateAppleJWSChainWithRoots(testAppleJWS(t, "ES256", chain, time.Now()), testAppleTrustedRoots(t, chain)); err == nil {
t.Fatal("validateAppleJWSChain() accepted certificates without Apple signing extensions")
}
}
@@ -58,7 +74,7 @@ func TestValidateAppleJWSChainRejectsNonAppleSigningCertificates(t *testing.T) {
func TestValidateAppleJWSChainUsesSignedDateForHistoricalPayload(t *testing.T) {
signedAt := time.Now().AddDate(-2, 0, 0)
chain := testAppleCertificateChainAt(t, signedAt, true)
if err := validateAppleJWSChain(testAppleJWS(t, "ES256", chain, signedAt)); err != nil {
if err := validateAppleJWSChainWithRoots(testAppleJWS(t, "ES256", chain, signedAt), testAppleTrustedRoots(t, chain)); err != nil {
t.Fatalf("validateAppleJWSChain() rejected historical payload: %v", err)
}
}
@@ -78,17 +94,17 @@ func TestValidateAppleJWSChainUsesNestedSignedDateForNotification(t *testing.T)
if err != nil {
t.Fatal(err)
}
outer := base64.RawURLEncoding.EncodeToString(header) + "." + base64.RawURLEncoding.EncodeToString(payload) + ".signature"
if err := validateAppleJWSChain(outer); err != nil {
outer := testAppleSignedJWS(t, header, payload, chain)
if err := validateAppleJWSChainWithRoots(outer, testAppleTrustedRoots(t, chain)); err != nil {
t.Fatalf("validateAppleJWSChain() rejected historical notification: %v", err)
}
}
func TestValidateAppleJWSChainAcceptsExpiredChainWithoutSignedDate(t *testing.T) {
func TestValidateAppleJWSChainRejectsExpiredChainWithoutSignedDate(t *testing.T) {
signedAt := time.Now().AddDate(-2, 0, 0)
chain := testAppleCertificateChainAt(t, signedAt, true)
if err := validateAppleJWSChain(testAppleJWSWithoutDate(t, chain)); err != nil {
t.Fatalf("validateAppleJWSChain() rejected an expired chain without signedDate: %v", err)
if err := validateAppleJWSChainWithRoots(testAppleJWSWithoutDate(t, chain), testAppleTrustedRoots(t, chain)); err == nil {
t.Fatal("validateAppleJWSChain() accepted an expired chain without signedDate")
}
}
@@ -96,7 +112,7 @@ func TestValidateAppleJWSChainRejectsBrokenChainWithoutSignedDate(t *testing.T)
chain := testAppleCertificateChain(t)
attackerChain := testAppleCertificateChain(t)
chain[0] = attackerChain[0]
if err := validateAppleJWSChain(testAppleJWSWithoutDate(t, chain)); err == nil {
if err := validateAppleJWSChainWithRoots(testAppleJWSWithoutDate(t, chain), testAppleTrustedRoots(t, chain)); err == nil {
t.Fatal("validateAppleJWSChain() accepted a broken chain without signedDate")
}
}
@@ -169,11 +185,13 @@ func testAppleCertificateChainAt(t *testing.T, validAt time.Time, includeAppleEx
}}
}
leafDER := testAppleCertificate(t, leafTemplate, intermediate, &leafKey.PublicKey, intermediateKey)
return []string{
chain := []string{
base64.StdEncoding.EncodeToString(leafDER),
base64.StdEncoding.EncodeToString(intermediateDER),
base64.StdEncoding.EncodeToString(rootDER),
}
testAppleLeafKeys[chain[0]] = leafKey
return chain
}
func testAppleECDSAKey(t *testing.T) *ecdsa.PrivateKey {
@@ -204,7 +222,7 @@ func testAppleJWS(t *testing.T, algorithm string, chain []string, signedAt time.
if err != nil {
t.Fatal(err)
}
return base64.RawURLEncoding.EncodeToString(header) + "." + base64.RawURLEncoding.EncodeToString(payload) + ".signature"
return testAppleSignedJWS(t, header, payload, chain)
}
func testAppleJWSWithoutDate(t *testing.T, chain []string) string {
@@ -217,5 +235,36 @@ func testAppleJWSWithoutDate(t *testing.T, chain []string) string {
if err != nil {
t.Fatal(err)
}
return base64.RawURLEncoding.EncodeToString(header) + "." + base64.RawURLEncoding.EncodeToString(payload) + ".signature"
return testAppleSignedJWS(t, header, payload, chain)
}
var testAppleLeafKeys = map[string]*ecdsa.PrivateKey{}
func testAppleSignedJWS(t *testing.T, header, payload []byte, chain []string) string {
t.Helper()
headerSegment := base64.RawURLEncoding.EncodeToString(header)
payloadSegment := base64.RawURLEncoding.EncodeToString(payload)
key := testAppleLeafKeys[chain[0]]
if key == nil {
t.Fatal("missing test Apple leaf key")
}
digest := sha256.Sum256([]byte(headerSegment + "." + payloadSegment))
r, s, err := ecdsa.Sign(rand.Reader, key, digest[:])
if err != nil {
t.Fatal(err)
}
signature := make([]byte, 64)
r.FillBytes(signature[:32])
s.FillBytes(signature[32:])
return headerSegment + "." + payloadSegment + "." + base64.RawURLEncoding.EncodeToString(signature)
}
func testAppleTrustedRoots(t *testing.T, chain []string) map[string]struct{} {
t.Helper()
rootDER, err := base64.StdEncoding.DecodeString(chain[2])
if err != nil {
t.Fatal(err)
}
fingerprint := sha256.Sum256(rootDER)
return map[string]struct{}{hex.EncodeToString(fingerprint[:]): {}}
}