From 2cb0eb8639c3963ac11e7489a8b2a50df07ee3fc Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Tue, 28 Jan 2020 08:53:25 +0100 Subject: [PATCH] protocol: certificate generator Signed-off-by: Maciek Borzecki --- protocol/cert.go | 77 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 protocol/cert.go diff --git a/protocol/cert.go b/protocol/cert.go new file mode 100644 index 0000000..0ae2c68 --- /dev/null +++ b/protocol/cert.go @@ -0,0 +1,77 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package protocol + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "crypto/rand" + "crypto/tls" + "crypto/x509" + "crypto/x509/pkix" + "math/big" + "time" +) + +type DeviceCertificate struct { + key *ecdsa.PrivateKey + cert []byte +} + +func (d *DeviceCertificate) TLSCertificate() *tls.Certificate { + return &tls.Certificate{ + PrivateKey: d.key, + Certificate: [][]byte{d.cert}, + } +} + +// GenerateDeviceCertificate returns a device certificate +func GenerateDeviceCertificate(entity string) (*DeviceCertificate, error) { + limit := big.Int{} + limit.Lsh(big.NewInt(1), 128) + serial, err := rand.Int(rand.Reader, &limit) + if err != nil { + return nil, err + } + + priv, err := ecdsa.GenerateKey(elliptic.P384(), rand.Reader) + if err != nil { + return nil, err + } + + startTime := time.Now() + // 10 years from now + expireTime := startTime.AddDate(10, 0, 0) + + template := x509.Certificate{ + SerialNumber: serial, + Subject: pkix.Name{ + CommonName: entity, + Organization: []string{"mconnect"}, + OrganizationalUnit: []string{"mconnect"}, + }, + NotBefore: startTime, + NotAfter: expireTime, + BasicConstraintsValid: true, + } + selfSign := template + cert, err := x509.CreateCertificate(rand.Reader, &template, &selfSign, + &priv.PublicKey, priv) + if err != nil { + return nil, err + } + devcert := &DeviceCertificate{ + key: priv, + cert: cert, + } + return devcert, nil +}