diff --git a/attestation/ras/pca/pca.go b/attestation/ras/pca/pca.go old mode 100644 new mode 100755 index 29195aedd136c3398a12ee1cb7d110cc8ff78a73..fc072dcd95704615cf32335b2f9264b1954650dc --- a/attestation/ras/pca/pca.go +++ b/attestation/ras/pca/pca.go @@ -1,7 +1,162 @@ package pca -import "fmt" +import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "fmt" + "github.com/google/go-tpm-tools/simulator" + "github.com/google/go-tpm/tpm2" + "github.com/pkg/errors" + "math/big" + "time" +) +const ( + TPM_AES = "AES" + TPM_CBC = "CBC" + +) +type PCA struct{ + +} +type PrivacyCA interface { + GetEkCert(key IdentitySymKey,privateKey crypto.PrivateKey)([]byte,error) + VerifyEkCert(EkCert x509.Certificate)(bool,error) +} + +//返回的是解密后的ekcert +//函数功能:通过pca的私钥解密出一个对称密钥 +//并通过这个密钥对ekcert进行解密 +func (pca *PCA)GetEkCert(identitySymkey IdentitySymKey,pcaPri crypto.PrivateKey)([]byte,error){ + //调用AsymDecryptofTPM 解出所需要的对称密钥symKey + symKey,err := AsymDecryptofTPM(pcaPri,identitySymkey.TPMAsymmetricKey.TPMEncscheme,identitySymkey.AsymBlob,nil) + // + if err!=nil{ + return nil, errors.Wrap(err,"GetEkCert() while process the AsymDecryptofTPM Error") + } + var ekCerts []byte + switch identitySymkey.TPMSymmetricKey.TPMEncscheme{ + case TPM_CBC: + //通过上面求出的对称密钥解出EKcert + ekCerts,err = SymetricEncrypt(identitySymkey.SymBlob,symKey,identitySymkey.TPMSymmetricKey.IV,TPM_AES,TPM_CBC) + if err!=nil{ + return nil,errors.Wrap(err,"GetEkCert() while process the SymetricEncrypt Error") + } + default: + return nil,errors.New("the TPM encScheme is Error") + } + return ekCerts, nil + +} +//生成一个新的pca接口 +func NewPCA(req Request)(PrivacyCA,error){ + if req.TPMVer == "2.0"{ + return &PCA{},nil + } + return nil, errors.New("NewPCA() Is a unsupported TPM") +} +//验证ek证书 +func (pca *PCA) VerifyEkCert(EkCert x509.Certificate)(bool,error){ + //验证Ek证书签名的认证 + //var opts x509.VerifyOptions + opts := x509.VerifyOptions{ + DNSName: "DNS", + Roots: nil, + KeyUsages: nil, + } + if _,err :=EkCert.Verify(opts);err!=nil{ + errors.New("failed to verify certificate") + return false, nil + } + return true, nil +} + +//通过pca的私钥作为签名,颁发Ak证书即生成AC +func GenerateAkCert(privacycaKey crypto.PrivateKey,privacycaCert *x509.Certificate,AkPub rsa.PublicKey)([]byte,error) { + //还未确定明白Templte中应该包含哪些 + serialNumber,err := rand.Int(rand.Reader,new(big.Int).Lsh(big.NewInt(1),128)) + if err!=nil{ + errors.New("create the serialNumber failed") + } + notBefore := time.Now() + notAfter := notBefore.Add(8760*time.Hour) + template := x509.Certificate{ + Version: 2.0, + SerialNumber: serialNumber, + Subject: pkix.Name{ + Organization: []string{},//there is a question + }, + NotBefore: notBefore, + NotAfter: notAfter, + IsCA: true, + KeyUsage: x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment| x509.KeyUsageCertSign, + BasicConstraintsValid: true, + }//通过x509.CreateCertificate()生成Akcert + AkCert,err := x509.CreateCertificate(rand.Reader,&template,privacycaCert,AkPub,privacycaKey) + if err!=nil{ + return nil, errors.Wrap(err,"while generate AkCert is error") + } + + return AkCert, err +} +func GetSignatureALG(pubKey crypto.PublicKey)(x509.SignatureAlgorithm,error){ + switch pubKey.(type){ + case *rsa.PublicKey: + return x509.SHA384WithRSA,nil + default: + return x509.UnknownSignatureAlgorithm,fmt.Errorf("there is a unknown pubKey type") + } +} +type IdentityResponse struct { + +} +//加密ac +func EncryptAkcert(AkCert []byte,AkName []byte)(ToACandSymKey,error){ + //对传进来的akCert进行加密,使用symKey作为加密密钥 + SymKey,err := CreateRandomByte(16) + if err != nil{ + errors.New("failed create the symkey of a random byte") + } + simulator,err := simulator.Get() + if err!=nil{ + errors.New("failed get the simulator") + } + + iv ,err := CreateRandomByte(16) + if err!=nil{ + errors.New("failed create the iv of a random byte") + } + encryptAC,err := SymetricEncrypt(AkCert,SymKey,iv,TPM_AES,TPM_CBC) + + if err!=nil{ + errors.New("failed the SymetricEncrypt") + } + parentHandle,_,err := tpm2.CreatePrimary(simulator,tpm2.HandleOwner, PcrSelection, ParentPassword, DefaultPassword, DefaultKeyParams) + if err!=nil{ + errors.New("failed CreatePrimary") + } + //generate the credential + credentialSecret,credentialBlob,err := tpm2.MakeCredential(simulator,parentHandle,AkCert,AkName) + if err!=nil{ + errors.New("failed the MakeCredential") + } + + symKeyParams := TPMSymKeyParams{ + EncryptAC: encryptAC, + IV: iv, + } + toACandsymKey := ToACandSymKey{ + Secret: credentialSecret, + Credential: credentialBlob, + TPMSymKeyParams: symKeyParams, + + } + + return toACandsymKey,nil +} func Test() { fmt.Println("hello, this is pca!") } diff --git a/attestation/ras/pca/pca_test.go b/attestation/ras/pca/pca_test.go new file mode 100755 index 0000000000000000000000000000000000000000..c28812e8cad1cb13d10ff8bc9f1d1f492f4ed538 --- /dev/null +++ b/attestation/ras/pca/pca_test.go @@ -0,0 +1,58 @@ +package pca + +import ( + "crypto" + "crypto/rsa" + "crypto/x509" + "fmt" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "testing" +) + +//test + +var req = Request{ + TPMVer: "2.0", + +} + +func TestPCAForUnsupportedTpm(t *testing.T) { + //测试TPM的版本 + req.TPMVer = "1.0" + _,err := NewPCA(req) + assert.Error(t, err) +} +func TestVerifyEkCert(t *testing.T){ + fmt.Println("This is a test of VerifyEkCert") + + var ekcert x509.Certificate + pca,err := NewPCA(req) + if err!=nil{ + errors.New("Create a new pca Error") + } + + Bool,_:=pca.VerifyEkCert(ekcert) + if !Bool{ + fmt.Println("Verify EkCert is failed!") + }else{ + fmt.Println("Verify EkCert is success!") + } +} +func TestGenerateAkCert(t *testing.T) { + fmt.Println("This is a test of GenerateAkCert") + // + var pcaPriv crypto.PrivateKey + //var pcaPub crypto.PublicKey + var pcaCert *x509.Certificate + var akPub rsa.PublicKey + _,err := GenerateAkCert(pcaPriv,pcaCert,akPub) + assert.NoError(t, err) +} +func TestEncryptAkcert(t *testing.T) { + var akCert,_ = CreateRandomByte(16) + akName:=[]byte{0, 11, 63, 66, 56, 152, 253, 128, 164, 49, 231, 162, 169, 14, 118, 72, 248, 151, 117, 166, 215, + 235, 210, 181, 92, 167, 94, 113, 24, 131, 10, 5, 12, 85, 252} + _,err := EncryptAkcert(akCert,akName) + assert.NoError(t, err) +} diff --git a/attestation/ras/pca/struct.go b/attestation/ras/pca/struct.go new file mode 100755 index 0000000000000000000000000000000000000000..81ea83f28166fe66a347715d8dfca023e7b7ec8e --- /dev/null +++ b/attestation/ras/pca/struct.go @@ -0,0 +1,73 @@ + +package pca + + +import ( + "crypto/rsa" + "github.com/google/go-tpm/tpm2" +) + +//定义几个相关的结构体,用于存放相关信息 +// +var( + PcrSelection = tpm2.PCRSelection{Hash: tpm2.AlgSHA1,PCRs: []int{0}} + ParentPassword=" " + DefaultPassword = "\x01\x02\x03\x04" + DefaultKeyParams = tpm2.Public{ + Type: tpm2.AlgRSA, + NameAlg: tpm2.AlgSHA1, + Attributes: tpm2.FlagStorageDefault, + RSAParameters: &tpm2.RSAParams{ + Symmetric: &tpm2.SymScheme{ + Alg: tpm2.AlgAES, + KeyBits: 128, + Mode: tpm2.AlgCFB, + }, + KeyBits: 2048, + ExponentRaw: 1<<16+1, + }, + } +) +type ToACandSymKey struct{ + Secret []byte + Credential []byte + TPMSymKeyParams TPMSymKeyParams + SymBlob []byte +} +type TPMSymKeyParams struct{ + //可能还要存放加密的算法等参数 + TPMSymAlgorithm string + TPMEncscheme string + + EncryptAC []byte + IV []byte +} +type TPMAsymKeyParams struct{ + + TPMAsymAlgorithm string + TPMEncscheme string + +} +type Request struct{ + //身份请求 + TPMVer string //TPM版本 + AkPub *rsa.PublicKey + AkName []byte //ak名字 + +} +type IdentitySymKey struct{ + //身份会话密钥内容 + IdentityReq Request + TPMAsymmetricKey TPMAsymKeyParams + TPMSymmetricKey TPMSymKeyParams + SymBlob []byte //用于存放加密后的身份证明 + AsymBlob []byte //用以存放加密的会话密钥 +} + + +type KeyPub interface { + +} +type KeyPri interface { + +} \ No newline at end of file diff --git a/attestation/ras/pca/utils.go b/attestation/ras/pca/utils.go new file mode 100755 index 0000000000000000000000000000000000000000..db88964146a7ed6c582edbcd08155cbc5e1fbaea --- /dev/null +++ b/attestation/ras/pca/utils.go @@ -0,0 +1,81 @@ +package pca + +import ( + "bytes" + "crypto" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "crypto/rsa" + "crypto/sha256" + "github.com/pkg/errors" + "io" +) + +const( + Tpm_ID_SHA256 =0x00B + Tpm_Sym_CBC =255 + Tpm_AES =0x6 + +) +//对加密等的操作 +func SymetricByCBCEncrypt(pay,iv []byte,block cipher.Block)([]byte,error){ + //通过block和iv使用CBC加密方式对pay进行加密 + //通过调用NewCBCEncrypter返回一个大小与iv相同的加密模式 + blockMode :=cipher.NewCBCEncrypter(block,iv) + paddspare :=block.BlockSize() - len(pay)%block.BlockSize() + paddtext := bytes.Repeat([]byte{byte(paddspare)},paddspare) + withPadding :=append(pay,paddtext...) + encryptByte := make([]byte,len(withPadding)) + blockMode.CryptBlocks(encryptByte,withPadding) + return encryptByte, nil +} +//make the payload encrypt by key and iv with something +func SymetricEncrypt(symblob ,key ,iv []byte,algorithm ,encScheme string)([]byte,error){ + //pay是需要加密的数据,key和iv是两个加密的参数, + //encScheme是加密策略,algorithm是加密算法 + //日志 + //先判断格式数据是否正确 + if len(symblob)==0||len(key)==0||len(iv)==0{ + return nil,errors.New("pay or key or iv may be a nil") + } + //通过算法进行相应的加密 + if algorithm ==TPM_AES{ + cipherblock,err := aes.NewCipher(key) + if err!=nil{ + return nil,errors.New("NewCipher is Error!") + } + switch encScheme { + case TPM_CBC: + return SymetricByCBCEncrypt(symblob,iv,cipherblock) + default: + return nil, errors.New("SymetricEncrypt() Unsupported the sym algorithm scheme") + } + } + return nil, nil +} +//TPM2下对非对称解密 +//prikey 表示私钥,enscheme表示加密方案 +func AsymDecryptofTPM(priKey crypto.PrivateKey,encScheme string,blob []byte,label []byte)([]byte,error){ + //使用私钥priKey 在encsheme方案下对blob进行解密 + if encScheme == "SHA256"{ + var rng io.Reader + decryptedBlobBytes,err := rsa.DecryptOAEP(sha256.New(),rng,priKey.(*rsa.PrivateKey),blob,label) + if err!=nil{ + + } + return decryptedBlobBytes,nil + } + return rsa.DecryptPKCS1v15(rand.Reader,priKey.(*rsa.PrivateKey),blob) +} +//生成长度是length的 byte类型的随机数 +//随机函数的生成:CreateRandomByte +func CreateRandomByte(len int)([]byte,error){ + //参数为生成的随机数的长度(字节),返回值为这个随机数 + b := make([]byte,len) + _,err := rand.Read(b) //调用Read函数 + if err!=nil{ + return nil,err + } + return b,nil +} \ No newline at end of file