// CreateCertificateSet requests the creation of a new transaction certificate set by the TCA. func (tcap *TCAP) CreateCertificateSet(ctx context.Context, in *pb.TCertCreateSetReq) (*pb.TCertCreateSetResp, error) { Trace.Println("grpc TCAP:CreateCertificateSet") id := in.Id.Id raw, err := tcap.tca.eca.readCertificate(id, x509.KeyUsageDigitalSignature) if err != nil { return nil, err } cert, err := x509.ParseCertificate(raw) if err != nil { return nil, err } pub := cert.PublicKey.(*ecdsa.PublicKey) r, s := big.NewInt(0), big.NewInt(0) r.UnmarshalText(in.Sig.R) s.UnmarshalText(in.Sig.S) //sig := in.Sig in.Sig = nil hash := primitives.NewHash() raw, _ = proto.Marshal(in) hash.Write(raw) if ecdsa.Verify(pub, hash.Sum(nil), r, s) == false { return nil, errors.New("signature does not verify") } // Generate nonce for TCertIndex nonce := make([]byte, 16) // 8 bytes rand, 8 bytes timestamp rand.Reader.Read(nonce[:8]) mac := hmac.New(primitives.GetDefaultHash(), tcap.tca.hmacKey) raw, _ = x509.MarshalPKIXPublicKey(pub) mac.Write(raw) kdfKey := mac.Sum(nil) num := int(in.Num) if num == 0 { num = 1 } // the batch of TCerts var set []*pb.TCert for i := 0; i < num; i++ { tcertid := util.GenerateIntUUID() // Compute TCertIndex tidx := []byte(strconv.Itoa(2*i + 1)) tidx = append(tidx[:], nonce[:]...) tidx = append(tidx[:], Padding...) mac := hmac.New(primitives.GetDefaultHash(), kdfKey) mac.Write([]byte{1}) extKey := mac.Sum(nil)[:32] mac = hmac.New(primitives.GetDefaultHash(), kdfKey) mac.Write([]byte{2}) mac = hmac.New(primitives.GetDefaultHash(), mac.Sum(nil)) mac.Write(tidx) one := new(big.Int).SetInt64(1) k := new(big.Int).SetBytes(mac.Sum(nil)) k.Mod(k, new(big.Int).Sub(pub.Curve.Params().N, one)) k.Add(k, one) tmpX, tmpY := pub.ScalarBaseMult(k.Bytes()) txX, txY := pub.Curve.Add(pub.X, pub.Y, tmpX, tmpY) txPub := ecdsa.PublicKey{Curve: pub.Curve, X: txX, Y: txY} // Compute encrypted TCertIndex encryptedTidx, err := CBCEncrypt(extKey, tidx) if err != nil { return nil, err } // TODO: We are storing each K used on the TCert in the ks array (the second return value of this call), but not returning it to the user. // We need to design a structure to return each TCert and the associated Ks. extensions, ks, err := tcap.generateExtensions(tcertid, encryptedTidx, cert, in.Attributes) if err != nil { return nil, err } spec := NewDefaultPeriodCertificateSpec(id, tcertid, &txPub, x509.KeyUsageDigitalSignature, extensions...) if raw, err = tcap.tca.createCertificateFromSpec(spec, in.Ts.Seconds, kdfKey); err != nil { Error.Println(err) return nil, err } set = append(set, &pb.TCert{raw, ks}) } return &pb.TCertCreateSetResp{&pb.CertSet{in.Ts, in.Id, kdfKey, set}}, nil }
func (tcap *TCAP) createCertificateSet(ctx context.Context, raw []byte, in *pb.TCertCreateSetReq) (*pb.TCertCreateSetResp, error) { var attrs = []*pb.ACAAttribute{} var err error var id = in.Id.Id var timestamp = in.Ts.Seconds const TCERT_SUBJECT_COMMON_NAME_VALUE string = "Transaction Certificate" if in.Attributes != nil && viper.GetBool("aca.enabled") { attrs, err = tcap.requestAttributes(id, raw, in.Attributes) if err != nil { return nil, err } } cert, err := x509.ParseCertificate(raw) if err != nil { return nil, err } pub := cert.PublicKey.(*ecdsa.PublicKey) r, s := big.NewInt(0), big.NewInt(0) r.UnmarshalText(in.Sig.R) s.UnmarshalText(in.Sig.S) //sig := in.Sig in.Sig = nil hash := primitives.NewHash() raw, _ = proto.Marshal(in) hash.Write(raw) if ecdsa.Verify(pub, hash.Sum(nil), r, s) == false { return nil, errors.New("signature does not verify") } // Generate nonce for TCertIndex nonce := make([]byte, 16) // 8 bytes rand, 8 bytes timestamp rand.Reader.Read(nonce[:8]) binary.LittleEndian.PutUint64(nonce[8:], uint64(in.Ts.Seconds)) mac := hmac.New(primitives.GetDefaultHash(), tcap.tca.hmacKey) raw, _ = x509.MarshalPKIXPublicKey(pub) mac.Write(raw) kdfKey := mac.Sum(nil) num := int(in.Num) if num == 0 { num = 1 } // the batch of TCerts var set []*pb.TCert for i := 0; i < num; i++ { tcertid := util.GenerateIntUUID() // Compute TCertIndex tidx := []byte(strconv.Itoa(2*i + 1)) tidx = append(tidx[:], nonce[:]...) tidx = append(tidx[:], Padding...) mac := hmac.New(primitives.GetDefaultHash(), kdfKey) mac.Write([]byte{1}) extKey := mac.Sum(nil)[:32] mac = hmac.New(primitives.GetDefaultHash(), kdfKey) mac.Write([]byte{2}) mac = hmac.New(primitives.GetDefaultHash(), mac.Sum(nil)) mac.Write(tidx) one := new(big.Int).SetInt64(1) k := new(big.Int).SetBytes(mac.Sum(nil)) k.Mod(k, new(big.Int).Sub(pub.Curve.Params().N, one)) k.Add(k, one) tmpX, tmpY := pub.ScalarBaseMult(k.Bytes()) txX, txY := pub.Curve.Add(pub.X, pub.Y, tmpX, tmpY) txPub := ecdsa.PublicKey{Curve: pub.Curve, X: txX, Y: txY} // Compute encrypted TCertIndex encryptedTidx, err := primitives.CBCPKCS7Encrypt(extKey, tidx) if err != nil { return nil, err } extensions, preK0, err := tcap.generateExtensions(tcertid, encryptedTidx, cert, attrs) if err != nil { return nil, err } spec := NewDefaultPeriodCertificateSpecWithCommonName(id, TCERT_SUBJECT_COMMON_NAME_VALUE, tcertid, &txPub, x509.KeyUsageDigitalSignature, extensions...) if raw, err = tcap.tca.createCertificateFromSpec(spec, timestamp, kdfKey, false); err != nil { Error.Println(err) return nil, err } set = append(set, &pb.TCert{Cert: raw, Prek0: preK0}) } tcap.tca.persistCertificateSet(id, timestamp, nonce, kdfKey) return &pb.TCertCreateSetResp{Certs: &pb.CertSet{Ts: in.Ts, Id: in.Id, Key: kdfKey, Certs: set}}, nil }