@@ -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