asn

package module
v1.0.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 9, 2023 License: MIT Imports: 10 Imported by: 0

README

github.com/satorunooshie/asn

Go Reference

Library for validation of App Store Server Notifications V2.

Usage

  • Set by file(s). Use NewFileRootCAFetcher.

  • Set by url(s). Use NewHTTPRootCAFetcher.

  • Set by raw(s). Use NewRawRootCAFetcher.

Recommended for use with the jwx created by lestrrat-go.

package asn

import (
	_ "embed"
	"fmt"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"strings"

	"github.com/lestrrat-go/jwx/v2/jws"
)

//go:embed testdata/Root-CA.cer
var rootCA []byte

//go:embed testdata/request.txt
var request []byte

//go:embed testdata/raw.txt
var raw []byte

const (
	emptyCerPath = "testdata/empty.cer"
	cerPath      = "testdata/Root-CA.cer"
	cerURL       = "https://www.apple.com/certificateauthority/AppleRootCA-G3.cer"
)

func path(filename string) string {
	return filepath.Join(filename)
}

type fakeAppleServer struct{}

func (*fakeAppleServer) RoundTrip(r *http.Request) (*http.Response, error) {
	res := httptest.NewRecorder()
	if r.URL.Host == "www.apple.com" {
		_, _ = res.Write(rootCA)
	}
	if strings.Contains(r.URL.String(), "notfound") {
		res.WriteHeader(http.StatusNotFound)
	}
	return res.Result(), nil
}

func ExampleNewKeyProvider_byFile() {
	kp := NewKeyProvider(NewFileRootCAFetcher(cerPath))
	opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
	verified, err := jws.Verify(request, opts...)
	fmt.Println(string(verified), err)
	// Output:
	// {"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
}

func ExampleNewKeyProvider_byFiles() {
	emptyCerPath := path(emptyCerPath)
	optional := []string{cerPath}
	kp := NewKeyProvider(NewFileRootCAFetcher(emptyCerPath, optional...))
	opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
	verified, err := jws.Verify(request, opts...)
	fmt.Println(string(verified), err)
	// Output:
	// {"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
}

func ExampleNewKeyProvider_byUrl() {
	client := &http.Client{
		Transport: &fakeAppleServer{},
	}
	kp := NewKeyProvider(NewHTTPRootCAFetcher(client, cerURL))
	opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
	verified, err := jws.Verify(request, opts...)
	fmt.Println(string(verified), err)
	// Output:
	// {"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
}

func ExampleNewKeyProvider_byUrls() {
	const url = "http://localhost:8080/test.cer"
	client := &http.Client{
		Transport: &fakeAppleServer{},
	}
	optional := []string{cerURL}
	kp := NewKeyProvider(NewHTTPRootCAFetcher(client, url, optional...))
	opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
	verified, err := jws.Verify(request, opts...)
	fmt.Println(string(verified), err)
	// Output:
	// {"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
}

func ExampleNewKeyProvider_byRaw() {
	kp := NewKeyProvider(NewRawRootCAFetcher(raw))
	opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
	verified, err := jws.Verify(request, opts...)
	fmt.Println(string(verified), err)
	// Output:
	// {"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
}

func ExampleNewKeyProvider_byRaws() {
	kp := NewKeyProvider(NewRawRootCAFetcher([]byte(`test`), raw))
	opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
	verified, err := jws.Verify(request, opts...)
	fmt.Println(string(verified), err)
	// Output:
	// {"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type FileRootCAFetcher

type FileRootCAFetcher struct {
	// contains filtered or unexported fields
}

FileRootCAFetcher implements RootCAFetcher via files.

func NewFileRootCAFetcher

func NewFileRootCAFetcher(cerpath string, optional ...string) *FileRootCAFetcher

NewFileRootCAFetcher returns a new FileRootCAFetcher. Optional string argument is for setting multiple Root CA file paths. At least one Root CA file path must be set.

func (*FileRootCAFetcher) Fetch

func (f *FileRootCAFetcher) Fetch(context.Context) ([][]byte, error)

Fetch returns the Root CAs from files set by NewFileRootCAFetcher. If there's cache, returns cache.

type HTTPRootCAFetcher

type HTTPRootCAFetcher struct {
	// contains filtered or unexported fields
}

HTTPRootCAFetcher implements RootCAFetcher via HTTP.

func NewHTTPRootCAFetcher

func NewHTTPRootCAFetcher(client *http.Client, url string, optional ...string) *HTTPRootCAFetcher

NewHTTPRootCAFetcher returns a new HTTPRootCAFetcher. At least one url that returns Root CA must be set. Optional string argument is for setting multiple urls that returns Root CA. if *http.Client is nil, http.DefaultClient is used.

func (*HTTPRootCAFetcher) Fetch

func (f *HTTPRootCAFetcher) Fetch(ctx context.Context) ([][]byte, error)

Fetch returns the Root CAs that were successfully fetched via http and an error if there's a problem with http access.

type KeyProvider

type KeyProvider struct {
	// contains filtered or unexported fields
}

KeyProvider implements jws.KeyProvider. Once pubkey verified, it's cached.

func NewKeyProvider

func NewKeyProvider(fetcher RootCAFetcher) *KeyProvider

NewKeyProvider returns a new KeyProvider.

Example (ByFile)
kp := NewKeyProvider(NewFileRootCAFetcher(cerPath))
opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
verified, err := jws.Verify(request, opts...)
fmt.Println(string(verified), err)
Output:

{"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
Example (ByFiles)
emptyCerPath := path(emptyCerPath)
optional := []string{cerPath}
kp := NewKeyProvider(NewFileRootCAFetcher(emptyCerPath, optional...))
opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
verified, err := jws.Verify(request, opts...)
fmt.Println(string(verified), err)
Output:

{"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
Example (ByRaw)
kp := NewKeyProvider(NewRawRootCAFetcher(raw))
opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
verified, err := jws.Verify(request, opts...)
fmt.Println(string(verified), err)
Output:

{"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
Example (ByRaws)
kp := NewKeyProvider(NewRawRootCAFetcher([]byte(`test`), raw))
opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
verified, err := jws.Verify(request, opts...)
fmt.Println(string(verified), err)
Output:

{"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
Example (ByUrl)
client := &http.Client{
	Transport: &fakeAppleServer{},
}
kp := NewKeyProvider(NewHTTPRootCAFetcher(client, cerURL))
opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
verified, err := jws.Verify(request, opts...)
fmt.Println(string(verified), err)
Output:

{"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>
Example (ByUrls)
const url = "http://localhost:8080/test.cer"
client := &http.Client{
	Transport: &fakeAppleServer{},
}
optional := []string{cerURL}
kp := NewKeyProvider(NewHTTPRootCAFetcher(client, url, optional...))
opts := []jws.VerifyOption{jws.WithKeyProvider(kp)}
verified, err := jws.Verify(request, opts...)
fmt.Println(string(verified), err)
Output:

{"notificationType":"DID_CHANGE_RENEWAL_PREF","subtype":"DOWNGRADE","notificationUUID":"c92e001c-96d2-9ou5-q92p-32a5fy0d6g78","notificationVersion":"2.0","data":{"appAppleId":982253034,"bundleId":"hogehoge","bundleVersion":"269822910.1","environment":"Production","signedRenewalInfo":"...","signedTransactionInfo":"..."}} <nil>

func (*KeyProvider) FetchKeys

func (p *KeyProvider) FetchKeys(ctx context.Context, sink jws.KeySink, sig *jws.Signature, msg *jws.Message) error

FetchKeys extracts the public key from the x5c field to verify the certificate according to https://datatracker.ietf.org/doc/html/rfc7515#section-4.1.6. Treat the chain that matches the root certificate fetched by RootCAFetcher as the root certificate.

type RawRootCAFetcher

type RawRootCAFetcher struct {
	// contains filtered or unexported fields
}

RawRootCAFetcher implements RootCAFetcher via raw bytes.

func NewRawRootCAFetcher

func NewRawRootCAFetcher(rootCA []byte, optional ...[]byte) *RawRootCAFetcher

NewRawRootCAFetcher returns a new RawRootCAFetcher. At least one certificate must be set as a byte string. Optional byte slice argument is for setting multiple Root CAs.

func (*RawRootCAFetcher) Fetch

func (f *RawRootCAFetcher) Fetch(context.Context) ([][]byte, error)

Fetch returns the Root CAs set by NewRawRootCAFetcher.

type RootCAFetcher

type RootCAFetcher interface {
	// Fetch returns Root CAs.
	Fetch(ctx context.Context) ([][]byte, error)
}

RootCAFetcher is an interface that fetches Root CA.

Directories

Path Synopsis
tools

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL