Skip to content

Commit ca0e18b

Browse files
committed
add: COSE Key Thumbprint (RFC 9679) feature and its test
Signed-off-by: Ken Takayama <[email protected]>
1 parent 58542e2 commit ca0e18b

File tree

2 files changed

+441
-0
lines changed

2 files changed

+441
-0
lines changed

key.go

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,112 @@ func (k *Key) PrivateKey() (crypto.PrivateKey, error) {
744744
}
745745
}
746746

747+
func (k *Key) Thumbprint(hash crypto.Hash) ([]byte, error) {
748+
if !hash.Available() {
749+
return nil, ErrUnavailableHashFunc
750+
}
751+
752+
type thumbprintHandler func() ([]byte, error)
753+
handlers := map[KeyType]thumbprintHandler{
754+
KeyTypeOKP: k.calcOKPThumbprint,
755+
KeyTypeEC2: k.calcEC2Thumbprint,
756+
}
757+
handler, ok := handlers[k.Type]
758+
if !ok {
759+
return nil, ErrOpNotSupported
760+
}
761+
762+
toBeHashedData, err := handler()
763+
if err != nil {
764+
return nil, err
765+
}
766+
767+
h := hash.New()
768+
h.Write(toBeHashedData)
769+
return h.Sum(nil), nil
770+
}
771+
772+
func (k *Key) calcOKPThumbprint() ([]byte, error) {
773+
t, ok := k.Params[KeyLabelOKPX]
774+
if !ok {
775+
return nil, ErrOKPNoPub
776+
}
777+
x, ok := t.([]byte)
778+
if !ok {
779+
return nil, ErrInvalidPubKey
780+
}
781+
782+
switch k.Params[KeyLabelOKPCurve] {
783+
case CurveEd25519:
784+
if len(x) != 32 {
785+
return nil, ErrInvalidPubKey
786+
}
787+
case CurveEd448:
788+
if len(x) != 57 {
789+
return nil, ErrInvalidPubKey
790+
}
791+
case CurveX25519:
792+
if len(x) != 32 {
793+
return nil, ErrInvalidPubKey
794+
}
795+
case CurveX448:
796+
if len(x) != 56 {
797+
return nil, ErrInvalidPubKey
798+
}
799+
default:
800+
return nil, ErrOpNotSupported
801+
}
802+
803+
m := make(map[int]interface{})
804+
m[1] = k.Type
805+
m[-1] = k.Params[KeyLabelOKPCurve]
806+
m[-2] = k.Params[KeyLabelEC2X]
807+
return encMode.Marshal(m)
808+
}
809+
810+
func (k *Key) calcEC2Thumbprint() ([]byte, error) {
811+
t, ok := k.Params[KeyLabelEC2X]
812+
if !ok {
813+
return nil, ErrEC2NoPub
814+
}
815+
x, ok := t.([]byte)
816+
if !ok {
817+
return nil, ErrInvalidPubKey
818+
}
819+
t, ok = k.Params[KeyLabelEC2Y]
820+
if !ok {
821+
return nil, ErrEC2NoPub
822+
}
823+
y, ok := t.([]byte)
824+
if !ok {
825+
return nil, ErrInvalidPubKey
826+
}
827+
828+
switch k.Params[KeyLabelEC2Curve] {
829+
case CurveP256:
830+
if len(x) != 32 || len(y) != 32 {
831+
return nil, ErrInvalidPubKey
832+
}
833+
case CurveP384:
834+
if len(x) != 48 || len(y) != 48 {
835+
return nil, ErrInvalidPubKey
836+
}
837+
case CurveP521:
838+
if len(x) != 66 || len(y) != 66 {
839+
return nil, ErrInvalidPubKey
840+
}
841+
default:
842+
return nil, ErrOpNotSupported
843+
}
844+
845+
m := make(map[int]interface{})
846+
m[1] = k.Type
847+
m[-1] = k.Params[KeyLabelEC2Curve]
848+
m[-2] = x
849+
m[-3] = y
850+
return encMode.Marshal(m)
851+
}
852+
747853
// AlgorithmOrDefault returns the Algorithm associated with Key. If
748854
// Key.Algorithm is set, that is what is returned. Otherwise, the algorithm is
749855
// inferred using Key.Curve. This method does NOT validate that Key.Algorithm,

0 commit comments

Comments
 (0)