如何为单元测试生成 Android Key Attestation 格式的证书?

How to generate certificate in Android Key Attestation format for unit tests?

我需要在服务器上验证由 Android 密钥证明过程生成的证书,但是我还没有访问真实设备的权限。

如何生成扩展字段与真实设备相同的 X.509 证书?

显然,根证书将是自签名的。

https://github.com/google/android-key-attestation/tree/master/server/examples中有示例如何使用我的值生成相同的证书?

我更喜欢服务器端 Java 和 Go。

除了使用真实设备之外,没有其他方法可以生成真实的 Google 签名证书。

出于测试目的,可以生成 Android 证书,其值与 Android 密钥证明过程生成的值相同,但是使用其他根证书签名。

预期的证书结构

代码如下: (1) 从文件 google-root-ca/google-1.pem 中读取 Google 根证书并将其作为模板创建一个具有相同内容的新证书。 (2) 使用步骤 (1) 中生成的根证书签署的硬件证明 ID 序列创建 Android 证书

package main

import (
    "crypto/ecdsa"
    "crypto/elliptic"
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "crypto/x509/pkix"
    "encoding/asn1"
    "encoding/pem"
    "io/ioutil"
    "math/big"
    "time"
)

func main() {
    rootCACertBytes, rootCAPrivKey, err := createCARoot()
    if err != nil {
        panic(err)
    }
    rootCACert, err := x509.ParseCertificate(rootCACertBytes)
    if err != nil {
        panic(err)
    }
    androidCertBytes, err := createAndroidKeystoreKey(rootCACert, rootCAPrivKey)
    if err != nil {
        panic(err)
    }
    err = printCertInPEM(rootCACertBytes, "CA.pem")
    if err != nil {
        panic(err)
    }
    err = printCertInPEM(androidCertBytes, "android.pem")
    if err != nil {
        panic(err)
    }
}

func createCARoot() ([]byte, *rsa.PrivateKey, error) {
    privKey, err := rsa.GenerateKey(rand.Reader, 4096)
    if err != nil {
        return nil, nil, err
    }
    certTemplate, err := readGoogleRootCA()
    if err != nil {
        return nil, nil, err
    }

    cert, err := x509.CreateCertificate(rand.Reader, certTemplate, certTemplate, privKey.Public(), privKey)
    if err != nil {
        return nil, nil, err
    }

    return cert, privKey, nil
}

func randomSerialNumber() (*big.Int, error) {
    serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
    return rand.Int(rand.Reader, serialNumberLimit)
}

func readGoogleRootCA() (*x509.Certificate, error) {
    pemBytes, err := ioutil.ReadFile("google-root-ca/google-1.pem")
    if err != nil {
        return nil, err
    }
    decoded, rest := pem.Decode(pemBytes)
    _ = rest
    return x509.ParseCertificate(decoded.Bytes)
}

func printCertInPEM(certBytes []byte, outFile string) error {
    return ioutil.WriteFile(outFile, pem.EncodeToMemory(
        &pem.Block{Type: "CERTIFICATE", Bytes: certBytes}), 0644)
}

var androidKeyAttestationOID = []int{1, 3, 6, 1, 4, 1, 11129, 2, 1, 17}

func createAndroidKeystoreKey(rootCACert *x509.Certificate, rootCAKey *rsa.PrivateKey) ([]byte, error) {
    privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
    if err != nil {
        return nil, err
    }

    expiration := time.Now().AddDate(10, 0, 0)
    serialNumber, err := randomSerialNumber()
    if err != nil {
        return nil, err
    }
    androidKeyAttestationExtension, err := CreateAndroidKeyAttestationExtension()
    if err != nil {
        return nil, err
    }
    certTemplate := &x509.Certificate{
        SerialNumber: serialNumber,
        Subject: pkix.Name{
            CommonName: "Android Keystore Key",
        },

        NotBefore: time.Now(),
        NotAfter:  expiration,

        KeyUsage: x509.KeyUsageDigitalSignature,
        ExtraExtensions: []pkix.Extension{
            {
                Id:    androidKeyAttestationOID,
                Value: androidKeyAttestationExtension,
            },
        },
    }

    return x509.CreateCertificate(rand.Reader, certTemplate, rootCACert, privKey.Public(), rootCAKey)
}

func CreateAndroidKeyAttestationExtension() ([]byte, error) {
    keyDesc := KeyDescription{
        AttestationVersion:       0,
        AttestationSecurityLevel: 1,
        KeymasterVersion:         0,
        KeymasterSecurityLevel:   0,
        AttestationChallenge:     []byte("abcdefg"),
        UniqueID:                 []byte{},
        SoftwareEnforced: AuthorizationList{
            AttestationIDSerial: []byte{},
        },
        TeeEnforced: AuthorizationList{
            AttestationIDSerial: []byte("00112233445566778899"),
        },
    }
    return asn1.Marshal(keyDesc)
}

type KeyDescription struct {
    AttestationVersion       int
    AttestationSecurityLevel asn1.Enumerated
    KeymasterVersion         int
    KeymasterSecurityLevel   asn1.Enumerated
    AttestationChallenge     []byte
    UniqueID                 []byte
    SoftwareEnforced         AuthorizationList
    TeeEnforced              AuthorizationList
}

// Values are commented out as nil values fail
type AuthorizationList struct {
    //Purpose                     []int       `asn1:"tag:1,explicit,set,optional"`
    //Algorithm                   int         `asn1:"tag:2,explicit,optional"`
    //KeySize                     int         `asn1:"tag:3,explicit,optional"`
    //Digest                      []int       `asn1:"tag:5,explicit,set,optional"`
    //Padding                     []int       `asn1:"tag:6,explicit,set,optional"`
    //EcCurve                     int         `asn1:"tag:10,explicit,optional"`
    //RsaPublicExponent           int         `asn1:"tag:200,explicit,optional"`
    //RollbackResistance          interface{} `asn1:"tag:303,explicit,optional"`
    //ActiveDateTime              int         `asn1:"tag:400,explicit,optional"`
    //OriginationExpireDateTime   int         `asn1:"tag:401,explicit,optional"`
    //UsageExpireDateTime         int         `asn1:"tag:402,explicit,optional"`
    //NoAuthRequired              interface{} `asn1:"tag:503,explicit,optional"`
    //UserAuthType                int         `asn1:"tag:504,explicit,optional"`
    //AuthTimeout                 int         `asn1:"tag:505,explicit,optional"`
    //AllowWhileOnBody            interface{} `asn1:"tag:506,explicit,optional"`
    //TrustedUserPresenceRequired interface{} `asn1:"tag:507,explicit,optional"`
    //TrustedConfirmationRequired interface{} `asn1:"tag:508,explicit,optional"`
    //UnlockedDeviceRequired      interface{} `asn1:"tag:509,explicit,optional"`
    //AllApplications             interface{} `asn1:"tag:600,explicit,optional"`
    //ApplicationID               interface{} `asn1:"tag:601,explicit,optional"`
    //CreationDateTime            int         `asn1:"tag:701,explicit,optional"`
    //Origin                      int         `asn1:"tag:702,explicit,optional"`
    //RootOfTrust                 RootOfTrust `asn1:"tag:704,explicit,optional"`
    //OsVersion                   int         `asn1:"tag:705,explicit,optional"`
    //OsPatchLevel                int         `asn1:"tag:706,explicit,optional"`
    //AttestationApplicationID    []byte      `asn1:"tag:709,explicit,optional"`
    //AttestationIDBrand          []byte      `asn1:"tag:710,explicit,optional"`
    //AttestationIDDevice         []byte      `asn1:"tag:711,explicit,optional"`
    //AttestationIDProduct        []byte      `asn1:"tag:712,explicit,optional"`
    AttestationIDSerial []byte `asn1:"tag:713,explicit,optional"`
    //AttestationIDImei           []byte      `asn1:"tag:714,explicit,optional"`
    //AttestationIDMeid           []byte      `asn1:"tag:715,explicit,optional"`
    //AttestationIDManufacturer   []byte      `asn1:"tag:716,explicit,optional"`
    //AttestationIDModel          []byte      `asn1:"tag:717,explicit,optional"`
    //VendorPatchLevel            int         `asn1:"tag:718,explicit,optional"`
    //BootPatchLevel              int         `asn1:"tag:719,explicit,optional"`
}

type RootOfTrust struct {
    VerifiedBootKey   []byte
    DeviceLocked      bool
    VerifiedBootState VerifiedBootState
    VerifiedBootHash  []byte
}

type VerifiedBootState int

const (
    Verified VerifiedBootState = iota
    SelfSigned
    Unverified
    Failed
)

google-root-ca/google-1.pem

second Google root certificate的内容保存到上面代码中使用的google-root-ca/google-1.pem中。