Beispiel #1
0
func (node *nodeImpl) initCryptoEngine() error {
	node.debug("Initializing node crypto engine...")

	// Init CLI
	node.eciesSPI = ecies.NewSPI()

	// Init certPools
	node.rootsCertPool = x509.NewCertPool()
	node.tlsCertPool = x509.NewCertPool()
	node.ecaCertPool = x509.NewCertPool()
	node.tcaCertPool = x509.NewCertPool()

	// Load ECA certs chain
	if err := node.loadECACertsChain(); err != nil {
		return err
	}

	// Load TCA certs chain
	if err := node.loadTCACertsChain(); err != nil {
		return err
	}

	// Load enrollment secret key
	if err := node.loadEnrollmentKey(); err != nil {
		return err
	}

	// Load enrollment certificate and set validator ID
	if err := node.loadEnrollmentCertificate(); err != nil {
		return err
	}

	// Load enrollment id
	if err := node.loadEnrollmentID(); err != nil {
		return err
	}

	// Load enrollment chain key
	if err := node.loadEnrollmentChainKey(); err != nil {
		return err
	}

	// Load TLS certs chain certificate
	if err := node.loadTLSCACertsChain(); err != nil {
		return err
	}

	// Load tls certificate
	if err := node.loadTLSCertificate(); err != nil {
		return err
	}

	node.debug("Initializing node crypto engine...done!")

	return nil
}
Beispiel #2
0
func (node *nodeImpl) registerCryptoEngine(enrollID, enrollPWD string) error {
	node.debug("Registering node crypto engine...")

	// Init CLI
	node.eciesSPI = ecies.NewSPI()

	if err := node.initTLS(); err != nil {
		node.error("Failed initliazing TLS [%s].", err.Error())

		return err
	}

	if err := node.retrieveECACertsChain(enrollID); err != nil {
		node.error("Failed retrieving ECA certs chain [%s].", err.Error())

		return err
	}

	if err := node.retrieveTCACertsChain(enrollID); err != nil {
		node.error("Failed retrieving ECA certs chain [%s].", err.Error())

		return err
	}

	if err := node.retrieveEnrollmentData(enrollID, enrollPWD); err != nil {
		node.error("Failed retrieving enrollment data [%s].", err.Error())

		return err
	}

	if err := node.retrieveTLSCertificate(enrollID, enrollPWD); err != nil {
		node.error("Failed retrieving enrollment data: %s", err)

		return err
	}

	node.debug("Registering node crypto engine...done!")

	return nil
}
Beispiel #3
0
//helper function for multiple tests
func enrollUser(user *User) error {

	ecap := &ECAP{eca}

	// Phase 1 of the protocol: Generate crypto material
	signPriv, err := primitives.NewECDSAKey()
	user.enrollPrivKey = signPriv
	if err != nil {
		return err
	}
	signPub, err := x509.MarshalPKIXPublicKey(&signPriv.PublicKey)
	if err != nil {
		return err
	}

	encPriv, err := primitives.NewECDSAKey()
	if err != nil {
		return err
	}
	encPub, err := x509.MarshalPKIXPublicKey(&encPriv.PublicKey)
	if err != nil {
		return err
	}

	req := &pb.ECertCreateReq{
		Ts:   &google_protobuf.Timestamp{Seconds: time.Now().Unix(), Nanos: 0},
		Id:   &pb.Identity{Id: user.enrollID},
		Tok:  &pb.Token{Tok: user.enrollPwd},
		Sign: &pb.PublicKey{Type: pb.CryptoType_ECDSA, Key: signPub},
		Enc:  &pb.PublicKey{Type: pb.CryptoType_ECDSA, Key: encPub},
		Sig:  nil}

	resp, err := ecap.CreateCertificatePair(context.Background(), req)
	if err != nil {
		return err
	}

	//Phase 2 of the protocol
	spi := ecies.NewSPI()
	eciesKey, err := spi.NewPrivateKey(nil, encPriv)
	if err != nil {
		return err
	}

	ecies, err := spi.NewAsymmetricCipherFromPublicKey(eciesKey)
	if err != nil {
		return err
	}

	out, err := ecies.Process(resp.Tok.Tok)
	if err != nil {
		return err
	}

	req.Tok.Tok = out
	req.Sig = nil

	hash := primitives.NewHash()
	raw, _ := proto.Marshal(req)
	hash.Write(raw)

	r, s, err := ecdsa.Sign(rand.Reader, signPriv, hash.Sum(nil))
	if err != nil {
		return err
	}
	R, _ := r.MarshalText()
	S, _ := s.MarshalText()
	req.Sig = &pb.Signature{Type: pb.CryptoType_ECDSA, R: R, S: S}

	resp, err = ecap.CreateCertificatePair(context.Background(), req)
	if err != nil {
		return err
	}

	// Verify we got valid crypto material back
	x509SignCert, err := primitives.DERToX509Certificate(resp.Certs.Sign)
	if err != nil {
		return err
	}

	_, err = primitives.GetCriticalExtension(x509SignCert, ECertSubjectRole)
	if err != nil {
		return err
	}

	x509EncCert, err := primitives.DERToX509Certificate(resp.Certs.Enc)
	if err != nil {
		return err
	}

	_, err = primitives.GetCriticalExtension(x509EncCert, ECertSubjectRole)
	if err != nil {
		return err
	}

	return nil
}
Beispiel #4
0
func (node *nodeImpl) getEnrollmentCertificateFromECA(id, pw string) (interface{}, []byte, []byte, error) {
	// Get a new ECA Client
	sock, ecaP, err := node.getECAClient()
	defer sock.Close()

	// Run the protocol

	signPriv, err := primitives.NewECDSAKey()
	if err != nil {
		node.Errorf("Failed generating ECDSA key [%s].", err.Error())

		return nil, nil, nil, err
	}
	signPub, err := x509.MarshalPKIXPublicKey(&signPriv.PublicKey)
	if err != nil {
		node.Errorf("Failed mashalling ECDSA key [%s].", err.Error())

		return nil, nil, nil, err
	}

	encPriv, err := primitives.NewECDSAKey()
	if err != nil {
		node.Errorf("Failed generating Encryption key [%s].", err.Error())

		return nil, nil, nil, err
	}
	encPub, err := x509.MarshalPKIXPublicKey(&encPriv.PublicKey)
	if err != nil {
		node.Errorf("Failed marshalling Encryption key [%s].", err.Error())

		return nil, nil, nil, err
	}

	req := &membersrvc.ECertCreateReq{
		Ts:   &timestamp.Timestamp{Seconds: time.Now().Unix(), Nanos: 0},
		Id:   &membersrvc.Identity{Id: id},
		Tok:  &membersrvc.Token{Tok: []byte(pw)},
		Sign: &membersrvc.PublicKey{Type: membersrvc.CryptoType_ECDSA, Key: signPub},
		Enc:  &membersrvc.PublicKey{Type: membersrvc.CryptoType_ECDSA, Key: encPub},
		Sig:  nil}

	resp, err := ecaP.CreateCertificatePair(context.Background(), req)
	if err != nil {
		node.Errorf("Failed invoking CreateCertficatePair [%s].", err.Error())

		return nil, nil, nil, err
	}

	if resp.FetchResult != nil && resp.FetchResult.Status != membersrvc.FetchAttrsResult_SUCCESS {
		node.Warning(resp.FetchResult.Msg)
	}
	//out, err := rsa.DecryptPKCS1v15(rand.Reader, encPriv, resp.Tok.Tok)
	spi := ecies.NewSPI()
	eciesKey, err := spi.NewPrivateKey(nil, encPriv)
	if err != nil {
		node.Errorf("Failed parsing decrypting key [%s].", err.Error())

		return nil, nil, nil, err
	}

	ecies, err := spi.NewAsymmetricCipherFromPublicKey(eciesKey)
	if err != nil {
		node.Errorf("Failed creating asymmetrinc cipher [%s].", err.Error())

		return nil, nil, nil, err
	}

	out, err := ecies.Process(resp.Tok.Tok)
	if err != nil {
		node.Errorf("Failed decrypting toke [%s].", err.Error())

		return nil, nil, nil, err
	}

	req.Tok.Tok = out
	req.Sig = nil

	hash := primitives.NewHash()
	raw, _ := proto.Marshal(req)
	hash.Write(raw)

	r, s, err := ecdsa.Sign(rand.Reader, signPriv, hash.Sum(nil))
	if err != nil {
		node.Errorf("Failed signing [%s].", err.Error())

		return nil, nil, nil, err
	}
	R, _ := r.MarshalText()
	S, _ := s.MarshalText()
	req.Sig = &membersrvc.Signature{Type: membersrvc.CryptoType_ECDSA, R: R, S: S}

	resp, err = ecaP.CreateCertificatePair(context.Background(), req)
	if err != nil {
		node.Errorf("Failed invoking CreateCertificatePair [%s].", err.Error())

		return nil, nil, nil, err
	}

	// Verify response

	// Verify cert for signing
	node.Debugf("Enrollment certificate for signing [% x]", primitives.Hash(resp.Certs.Sign))

	x509SignCert, err := primitives.DERToX509Certificate(resp.Certs.Sign)
	if err != nil {
		node.Errorf("Failed parsing signing enrollment certificate for signing: [%s]", err)

		return nil, nil, nil, err
	}

	_, err = primitives.GetCriticalExtension(x509SignCert, ECertSubjectRole)
	if err != nil {
		node.Errorf("Failed parsing ECertSubjectRole in enrollment certificate for signing: [%s]", err)

		return nil, nil, nil, err
	}

	err = primitives.CheckCertAgainstSKAndRoot(x509SignCert, signPriv, node.ecaCertPool)
	if err != nil {
		node.Errorf("Failed checking signing enrollment certificate for signing: [%s]", err)

		return nil, nil, nil, err
	}

	// Verify cert for encrypting
	node.Debugf("Enrollment certificate for encrypting [% x]", primitives.Hash(resp.Certs.Enc))

	x509EncCert, err := primitives.DERToX509Certificate(resp.Certs.Enc)
	if err != nil {
		node.Errorf("Failed parsing signing enrollment certificate for encrypting: [%s]", err)

		return nil, nil, nil, err
	}

	_, err = primitives.GetCriticalExtension(x509EncCert, ECertSubjectRole)
	if err != nil {
		node.Errorf("Failed parsing ECertSubjectRole in enrollment certificate for encrypting: [%s]", err)

		return nil, nil, nil, err
	}

	err = primitives.CheckCertAgainstSKAndRoot(x509EncCert, encPriv, node.ecaCertPool)
	if err != nil {
		node.Errorf("Failed checking signing enrollment certificate for encrypting: [%s]", err)

		return nil, nil, nil, err
	}

	return signPriv, resp.Certs.Sign, resp.Pkchain, nil
}
Beispiel #5
0
// CreateCertificatePair requests the creation of a new enrollment certificate pair by the ECA.
//
func (ecap *ECAP) CreateCertificatePair(ctx context.Context, in *pb.ECertCreateReq) (*pb.ECertCreateResp, error) {
	Trace.Println("gRPC ECAP:CreateCertificate")

	// validate token
	var tok, prev []byte
	var role, state int
	var enrollID string

	id := in.Id.Id
	err := ecap.eca.readUser(id).Scan(&role, &tok, &state, &prev, &enrollID)

	if err != nil || !bytes.Equal(tok, in.Tok.Tok) {
		return nil, errors.New("Identity or token does not match.")
	}

	ekey, err := x509.ParsePKIXPublicKey(in.Enc.Key)
	if err != nil {
		return nil, err
	}

	switch {
	case state == 0:
		// initial request, create encryption challenge
		tok = []byte(randomString(12))

		_, err = ecap.eca.db.Exec("UPDATE Users SET token=?, state=?, key=? WHERE id=?", tok, 1, in.Enc.Key, id)
		if err != nil {
			Error.Println(err)
			return nil, err
		}

		spi := ecies.NewSPI()
		eciesKey, err := spi.NewPublicKey(nil, ekey.(*ecdsa.PublicKey))
		if err != nil {
			return nil, err
		}

		ecies, err := spi.NewAsymmetricCipherFromPublicKey(eciesKey)
		if err != nil {
			return nil, err
		}

		out, err := ecies.Process(tok)
		return &pb.ECertCreateResp{Certs: nil, Chain: nil, Pkchain: nil, Tok: &pb.Token{Tok: out}}, err

	case state == 1:
		// ensure that the same encryption key is signed that has been used for the challenge
		if subtle.ConstantTimeCompare(in.Enc.Key, prev) != 1 {
			return nil, errors.New("Encryption keys do not match.")
		}

		// validate request signature
		sig := in.Sig
		in.Sig = nil

		r, s := big.NewInt(0), big.NewInt(0)
		r.UnmarshalText(sig.R)
		s.UnmarshalText(sig.S)

		if in.Sign.Type != pb.CryptoType_ECDSA {
			return nil, errors.New("Unsupported (signing) key type.")
		}
		skey, err := x509.ParsePKIXPublicKey(in.Sign.Key)
		if err != nil {
			return nil, err
		}

		hash := primitives.NewHash()
		raw, _ := proto.Marshal(in)
		hash.Write(raw)
		if ecdsa.Verify(skey.(*ecdsa.PublicKey), hash.Sum(nil), r, s) == false {
			return nil, errors.New("Signature verification failed.")
		}

		// create new certificate pair
		ts := time.Now().Add(-1 * time.Minute).UnixNano()

		spec := NewDefaultCertificateSpecWithCommonName(id, enrollID, skey.(*ecdsa.PublicKey), x509.KeyUsageDigitalSignature, pkix.Extension{Id: ECertSubjectRole, Critical: true, Value: []byte(strconv.Itoa(ecap.eca.readRole(id)))})
		sraw, err := ecap.eca.createCertificateFromSpec(spec, ts, nil)
		if err != nil {
			Error.Println(err)
			return nil, err
		}

		spec = NewDefaultCertificateSpecWithCommonName(id, enrollID, ekey.(*ecdsa.PublicKey), x509.KeyUsageDataEncipherment, pkix.Extension{Id: ECertSubjectRole, Critical: true, Value: []byte(strconv.Itoa(ecap.eca.readRole(id)))})
		eraw, err := ecap.eca.createCertificateFromSpec(spec, ts, nil)
		if err != nil {
			ecap.eca.db.Exec("DELETE FROM Certificates Where id=?", id)
			Error.Println(err)
			return nil, err
		}

		_, err = ecap.eca.db.Exec("UPDATE Users SET state=? WHERE id=?", 2, id)
		if err != nil {
			ecap.eca.db.Exec("DELETE FROM Certificates Where id=?", id)
			Error.Println(err)
			return nil, err
		}

		var obcECKey []byte
		if role == int(pb.Role_VALIDATOR) {
			obcECKey = ecap.eca.obcPriv
		} else {
			obcECKey = ecap.eca.obcPub
		}

		return &pb.ECertCreateResp{Certs: &pb.CertPair{Sign: sraw, Enc: eraw}, Chain: &pb.Token{Tok: ecap.eca.obcKey}, Pkchain: obcECKey, Tok: nil}, nil

	}

	return nil, errors.New("Invalid (=expired) certificate creation token provided.")
}