Skip to content
File

Blob: spec/pki/token.go

go93 lines
1package pki
2 
3import (
4 "crypto/x509"
5 "crypto/x509/pkix"
6 "encoding/base64"
7 "errors"
8 "strconv"
9 "strings"
10 
11 "go.miragespace.co/specter/spec/protocol"
12 "go.miragespace.co/specter/util"
13 
14 "go.uber.org/zap/zapcore"
15)
16 
17type TokenVersion string
18 
19const (
20 TokenSeparator string = ":"
21 TokenV1 TokenVersion = "v1" // CommonName: v1:clientID:oldToken before PKI is implemented, only the oldToken will be used
22 TokenV2 TokenVersion = "v2" // CommonName: v2:clientID:base64url(sha256(public key)) initial implementation of PKI, the entire CommonName will be used
23)
24 
25type Identity struct {
26 Token []byte
27 ID uint64
28 Version TokenVersion
29}
30 
31func (n *Identity) NodeIdentity() *protocol.Node {
32 return &protocol.Node{
33 Id: n.ID,
34 Address: string(n.Token),
35 Rendezvous: true,
36 }
37}
38 
39func MakeSubjectV1(id uint64, token string) pkix.Name {
40 return pkix.Name{
41 CommonName: strings.Join([]string{
42 string(TokenV1),
43 strconv.FormatUint(id, 10),
44 token,
45 }, TokenSeparator),
46 }
47}
48 
49func MakeSubjectV2(id uint64, hash []byte) pkix.Name {
50 return pkix.Name{
51 CommonName: strings.Join([]string{
52 string(TokenV2),
53 strconv.FormatUint(id, 10),
54 base64.URLEncoding.EncodeToString(hash),
55 }, TokenSeparator),
56 }
57}
58 
59func ExtractCertificateIdentity(cert *x509.Certificate) (*Identity, error) {
60 cn := cert.Subject.CommonName
61 parts := strings.SplitN(cn, ":", 3)
62 
63 if len(parts) != 3 {
64 return nil, errors.New("pki: invalid subject format")
65 }
66 
67 switch parts[0] {
68 case string(TokenV1):
69 return &Identity{
70 ID: util.Must(strconv.ParseUint(parts[1], 10, 64)),
71 Token: []byte(parts[2]),
72 Version: TokenV1,
73 }, nil
74 case string(TokenV2):
75 return &Identity{
76 ID: util.Must(strconv.ParseUint(parts[1], 10, 64)),
77 Token: []byte(cn),
78 Version: TokenV2,
79 }, nil
80 default:
81 return nil, errors.New("pki: unknown subject in certificate")
82 }
83}
84 
85var _ zapcore.ObjectMarshaler = (*Identity)(nil)
86 
87func (n *Identity) MarshalLogObject(enc zapcore.ObjectEncoder) error {
88 enc.AddUint64("id", n.ID)
89 enc.AddString("token", string(n.Token))
90 enc.AddString("version", string(n.Version))
91 return nil
92}