github.com/trustbloc/kms-go@v1.1.2/doc/util/fingerprint/fingerprint_test.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package fingerprint
     8  
     9  import (
    10  	"crypto/ecdsa"
    11  	"crypto/ed25519"
    12  	"crypto/elliptic"
    13  	"crypto/rand"
    14  	"crypto/rsa"
    15  	"encoding/base64"
    16  	"fmt"
    17  	"math/big"
    18  	"strings"
    19  	"testing"
    20  
    21  	"github.com/btcsuite/btcutil/base58"
    22  	"github.com/go-jose/go-jose/v3"
    23  	"github.com/stretchr/testify/assert"
    24  	"github.com/stretchr/testify/require"
    25  
    26  	"github.com/trustbloc/kms-go/doc/jose/jwk"
    27  	"github.com/trustbloc/kms-go/doc/jose/jwk/jwksupport"
    28  )
    29  
    30  func TestCreateDIDKey(t *testing.T) {
    31  	const (
    32  		edPubKeyBase58     = "B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u"
    33  		edExpectedDIDKey   = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
    34  		edExpectedDIDKeyID = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" //nolint:lll
    35  
    36  		bbsPubKeyBase58     = "25EEkQtcLKsEzQ6JTo9cg4W7NHpaurn4Wg6LaNPFq6JQXnrP91SDviUz7KrJVMJd76CtAZFsRLYzvgX2JGxo2ccUHtuHk7ELCWwrkBDfrXCFVfqJKDootee9iVaF6NpdJtBE"                                                                                                                                                    //nolint:lll
    37  		bbsExpectedDIDKey   = "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY"                                                                                                                                         //nolint:lll
    38  		bbsExpectedDIDKeyID = "did:key:zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY#zUC7K4ndUaGZgV7Cp2yJy6JtMoUHY6u7tkcSYUvPrEidqBmLCTLmi6d5WvwnUqejscAkERJ3bfjEiSYtdPkRSE8kSa11hFBr4sTgnbZ95SJj19PN2jdvJjyzpSZgxkyyxNnBNnY" //nolint:lll
    39  
    40  		ecP256PubKeyBase58     = "3YRwdf868zp2t8c4oT4XdYfCihMsfR1zrVYyXS5SS4FwQ7wftDfoY5nohvhdgSk9LxyfzjTLzffJPmHgFBqizX9v"
    41  		ecP256ExpectedDIDKey   = "did:key:zrurwcJZss4ruepVNu1H3xmSirvNbzgBk9qrCktB6kaewXnJAhYWwtP3bxACqBpzjZdN7TyHNzzGGSSH5qvZsSDir9z"                                                                                             //nolint:lll
    42  		ecP256ExpectedDIDKeyID = "did:key:zrurwcJZss4ruepVNu1H3xmSirvNbzgBk9qrCktB6kaewXnJAhYWwtP3bxACqBpzjZdN7TyHNzzGGSSH5qvZsSDir9z#zrurwcJZss4ruepVNu1H3xmSirvNbzgBk9qrCktB6kaewXnJAhYWwtP3bxACqBpzjZdN7TyHNzzGGSSH5qvZsSDir9z" //nolint:lll
    43  
    44  		ecP384PubKeyBase58     = "tAjHMcvoBXs3BSihDV85trHmstc3V3vTP7o2Si72eCWdVzeGgGvRd8h5neHEbqSL989h53yNj7M7wHckB2bKpGKQjnPDD7NphDa9nUUBggCB6aCWterfdXbH5DfWPZx5oXU"                                                                                                                                                     //nolint:lll
    45  		ecP384ExpectedDIDKey   = "did:key:zFwfeyrSyWdksRYykTGGtagWazFB5zS4CjQcxDMQSNmCTQB5QMqokx2VJz4vBB2hN1nUrYDTuYq3kd1BM5cUCfFD4awiNuzEBuoy6rZZTMCsZsdvWkDXY6832qcAnzE7YGw43KU"                                                                                                                                         //nolint:lll
    46  		ecP384ExpectedDIDKeyID = "did:key:zFwfeyrSyWdksRYykTGGtagWazFB5zS4CjQcxDMQSNmCTQB5QMqokx2VJz4vBB2hN1nUrYDTuYq3kd1BM5cUCfFD4awiNuzEBuoy6rZZTMCsZsdvWkDXY6832qcAnzE7YGw43KU#zFwfeyrSyWdksRYykTGGtagWazFB5zS4CjQcxDMQSNmCTQB5QMqokx2VJz4vBB2hN1nUrYDTuYq3kd1BM5cUCfFD4awiNuzEBuoy6rZZTMCsZsdvWkDXY6832qcAnzE7YGw43KU" //nolint:lll
    47  
    48  		ecP521PubKeyBase58     = "mTQ9pPr2wkKdiTHhVG7xmLwyJ5mrgq1FKcHFz2XJprs4zAPtjXWFiEz6vsscbseSEzGdjAVzcUhwdodT5cbrRjQqFdz8d1yYVqMHXsVCdCUrmWNNHcZLJeYCn1dCtQX9YRVdDFfnzczKFxDXe9HusLqBWTobbxVvdj9cTi7rSWVznP5Emfo"                                                                                                                                                                                                       //nolint:lll
    49  		ecP521ExpectedDIDKey   = "did:key:zWGhj2NTyCiehTPioanYSuSrfB7RJKwZj6bBUDNojfGEA21nr5NcBsHme7hcVSbptpWKarJpTcw814J3X8gVU9gZmeKM27JpGA5wNMzt8JZwjDyf8EzCJg5ve5GR2Xfm7d9Djp73V7s35KPeKe7VHMzmL8aPw4XBniNej5sXapPFoBs5R8m195HK"                                                                                                                                                                                          //nolint:lll
    50  		ecP521ExpectedDIDKeyID = "did:key:zWGhj2NTyCiehTPioanYSuSrfB7RJKwZj6bBUDNojfGEA21nr5NcBsHme7hcVSbptpWKarJpTcw814J3X8gVU9gZmeKM27JpGA5wNMzt8JZwjDyf8EzCJg5ve5GR2Xfm7d9Djp73V7s35KPeKe7VHMzmL8aPw4XBniNej5sXapPFoBs5R8m195HK#zWGhj2NTyCiehTPioanYSuSrfB7RJKwZj6bBUDNojfGEA21nr5NcBsHme7hcVSbptpWKarJpTcw814J3X8gVU9gZmeKM27JpGA5wNMzt8JZwjDyf8EzCJg5ve5GR2Xfm7d9Djp73V7s35KPeKe7VHMzmL8aPw4XBniNej5sXapPFoBs5R8m195HK" //nolint:lll
    51  
    52  		bbsPubKeyG1Base58       = "6TBZrWMsPSFrJ2u7xFNyNA6VZs3gWpCwLi4jk8gB9EQ1bgNYK2Zjsxhku68mypBHke"
    53  		bbsPubKeyG2Base58       = "26jjNXrWtHvbrVaiYBKcFRkCvzyTUfg1W4odspRJjfQRfoT33jr91dEn2wqzaWVVVw1WmFwpGxrioYvy3sbvgphfu2D4nJUvrmQ7ZtoykgXA4EuJhmmV3TnnfHnBkKKBWn5q"                                                                                                                                                                                                                                                                                        //nolint:lll
    54  		bbsExpectedG1G2DIDKey   = "did:key:z5TcDLDFhBEndYdwFKkQMgVTgtRHx2sniQisVxdiXZ96pcrRy2ehWvcHfhSrfDmozq8dQNxhu2u7y9FUKJ8R3VPZNPjEgsozTSx47WysNM9GESUMmyniFxbdbpxNdocx6SbRyf6nBTFzoXojbWjSsDN4LhNz1sAMzTXgh5HvLYtYzJXo1JtLZBwHgmvtWyEQqtxtjV2eo"                                                                                                                                                                                                           //nolint:lll
    55  		bbsExpectedG1G2DIDKeyID = "did:key:z5TcDLDFhBEndYdwFKkQMgVTgtRHx2sniQisVxdiXZ96pcrRy2ehWvcHfhSrfDmozq8dQNxhu2u7y9FUKJ8R3VPZNPjEgsozTSx47WysNM9GESUMmyniFxbdbpxNdocx6SbRyf6nBTFzoXojbWjSsDN4LhNz1sAMzTXgh5HvLYtYzJXo1JtLZBwHgmvtWyEQqtxtjV2eo#z5TcDLDFhBEndYdwFKkQMgVTgtRHx2sniQisVxdiXZ96pcrRy2ehWvcHfhSrfDmozq8dQNxhu2u7y9FUKJ8R3VPZNPjEgsozTSx47WysNM9GESUMmyniFxbdbpxNdocx6SbRyf6nBTFzoXojbWjSsDN4LhNz1sAMzTXgh5HvLYtYzJXo1JtLZBwHgmvtWyEQqtxtjV2eo" //nolint:lll
    56  	)
    57  
    58  	tests := []struct {
    59  		name     string
    60  		keyB58   string
    61  		DIDKey   string
    62  		DIDKeyID string
    63  		keyCode  uint64
    64  		crv      elliptic.Curve
    65  	}{
    66  		{
    67  			name:     "test ED25519",
    68  			keyB58:   edPubKeyBase58,
    69  			DIDKey:   edExpectedDIDKey,
    70  			DIDKeyID: edExpectedDIDKeyID,
    71  			keyCode:  ED25519PubKeyMultiCodec,
    72  		},
    73  		{
    74  			name:     "test BBS+",
    75  			keyB58:   bbsPubKeyBase58,
    76  			DIDKey:   bbsExpectedDIDKey,
    77  			DIDKeyID: bbsExpectedDIDKeyID,
    78  			keyCode:  BLS12381g2PubKeyMultiCodec,
    79  		},
    80  		{
    81  			name:     "test P-256",
    82  			keyB58:   ecP256PubKeyBase58,
    83  			DIDKey:   ecP256ExpectedDIDKey,
    84  			DIDKeyID: ecP256ExpectedDIDKeyID,
    85  			keyCode:  P256PubKeyMultiCodec,
    86  			crv:      elliptic.P256(),
    87  		},
    88  		{
    89  			name:     "test P-384",
    90  			keyB58:   ecP384PubKeyBase58,
    91  			DIDKey:   ecP384ExpectedDIDKey,
    92  			DIDKeyID: ecP384ExpectedDIDKeyID,
    93  			keyCode:  P384PubKeyMultiCodec,
    94  			crv:      elliptic.P384(),
    95  		},
    96  		{
    97  			name:     "test P-521",
    98  			keyB58:   ecP521PubKeyBase58,
    99  			DIDKey:   ecP521ExpectedDIDKey,
   100  			DIDKeyID: ecP521ExpectedDIDKeyID,
   101  			keyCode:  P521PubKeyMultiCodec,
   102  			crv:      elliptic.P521(),
   103  		},
   104  		{
   105  			name:     "test BBS+ with G1G2",
   106  			keyB58:   bbsPubKeyG2Base58,
   107  			DIDKey:   bbsExpectedG1G2DIDKey,
   108  			DIDKeyID: bbsExpectedG1G2DIDKeyID,
   109  			keyCode:  BLS12381g1g2PubKeyMultiCodec,
   110  		},
   111  	}
   112  
   113  	for _, test := range tests {
   114  		tc := test
   115  		t.Run(tc.name+" CreateDIDKey", func(t *testing.T) {
   116  			keyBytes := base58.Decode(tc.keyB58)
   117  			// append G1G2 public keys for Creation of DIDKey for BLS12381g1g2PubKeyMultiCodec
   118  			if tc.keyCode == BLS12381g1g2PubKeyMultiCodec {
   119  				g1Bytes := base58.Decode(bbsPubKeyG1Base58)
   120  				keyBytes = append(g1Bytes, keyBytes...)
   121  			}
   122  
   123  			didKey, keyID := CreateDIDKeyByCode(tc.keyCode, keyBytes)
   124  
   125  			require.Equal(t, tc.DIDKey, didKey)
   126  			require.Equal(t, tc.DIDKeyID, keyID)
   127  		})
   128  
   129  		t.Run(tc.name+" PubKeyFromFingerprint success", func(t *testing.T) {
   130  			pubKey, code, err := PubKeyFromFingerprint(strings.Split(tc.DIDKeyID, "#")[1])
   131  			require.Equal(t, tc.keyCode, code)
   132  			require.NoError(t, err)
   133  
   134  			require.Equal(t, base58.Encode(pubKey), tc.keyB58)
   135  		})
   136  
   137  		t.Run(tc.name+" PubKeyFromDIDKey", func(t *testing.T) {
   138  			pubKey, err := PubKeyFromDIDKey(tc.DIDKey)
   139  			if tc.crv != nil {
   140  				mKeyCompressed := append([]byte{4}, pubKey...)
   141  				x, y := elliptic.Unmarshal(tc.crv, mKeyCompressed)
   142  				mKey := elliptic.Marshal(tc.crv, x, y)
   143  				require.EqualValues(t, mKeyCompressed, mKey)
   144  			}
   145  
   146  			require.Equal(t, tc.keyB58, base58.Encode(pubKey))
   147  			require.NoError(t, err)
   148  		})
   149  	}
   150  
   151  	t.Run("test PubKeyFromFingerprint fail", func(t *testing.T) {
   152  		badDIDKeyID := "AB" + strings.Split(edExpectedDIDKeyID, "#")[1][2:]
   153  
   154  		_, _, err := PubKeyFromFingerprint(badDIDKeyID)
   155  		require.EqualError(t, err, "unknown key encoding")
   156  	})
   157  
   158  	t.Run("invalid fingerprint", func(t *testing.T) {
   159  		_, _, err := PubKeyFromFingerprint("")
   160  		require.Error(t, err)
   161  
   162  		_, _, err = PubKeyFromFingerprint("a6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH")
   163  		require.Error(t, err)
   164  	})
   165  }
   166  
   167  func readBigInt(t *testing.T, b64 string) *big.Int {
   168  	buf, err := base64.RawURLEncoding.DecodeString(b64)
   169  	require.Nil(t, err, "can't parse string as b64: %v\n%s", err, b64)
   170  
   171  	var x big.Int
   172  	x = *x.SetBytes(buf)
   173  
   174  	return &x
   175  }
   176  
   177  func TestCreateDIDKeyByJwk(t *testing.T) {
   178  	tests := []struct {
   179  		name     string
   180  		kty      string
   181  		curve    elliptic.Curve
   182  		valB58   string
   183  		x        string
   184  		y        string
   185  		DIDKey   string
   186  		DIDKeyID string
   187  	}{
   188  		{
   189  			name:     "test Ed25519",
   190  			kty:      "OKP",
   191  			valB58:   "B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u",
   192  			DIDKey:   "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH",
   193  			DIDKeyID: "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH", //nolint:lll
   194  		},
   195  		{
   196  			name:     "test X25519",
   197  			kty:      "OKP",
   198  			valB58:   "4Dy8E9UaZscuPUf2GLxV44RCNL7oxmEXXkgWXaug1WKV",
   199  			DIDKey:   "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F",
   200  			DIDKeyID: "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F#z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F", //nolint:lll
   201  		},
   202  		{
   203  			name:     "test P-256",
   204  			kty:      "EC",
   205  			curve:    elliptic.P256(),
   206  			x:        "igrFmi0whuihKnj9R3Om1SoMph72wUGeFaBbzG2vzns",
   207  			y:        "efsX5b10x8yjyrj4ny3pGfLcY7Xby1KzgqOdqnsrJIM",
   208  			DIDKey:   "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv",
   209  			DIDKeyID: "did:key:zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv#zDnaerx9CtbPJ1q36T5Ln5wYt3MQYeGRG5ehnPAmxcf5mDZpv", //nolint:lll
   210  		},
   211  		{
   212  			name:     "test P-384",
   213  			kty:      "EC",
   214  			curve:    elliptic.P384(),
   215  			x:        "lInTxl8fjLKp_UCrxI0WDklahi-7-_6JbtiHjiRvMvhedhKVdHBfi2HCY8t_QJyc",
   216  			y:        "y6N1IC-2mXxHreETBW7K3mBcw0qGr3CWHCs-yl09yCQRLcyfGv7XhqAngHOu51Zv",
   217  			DIDKey:   "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9",
   218  			DIDKeyID: "did:key:z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9#z82Lm1MpAkeJcix9K8TMiLd5NMAhnwkjjCBeWHXyu3U4oT2MVJJKXkcVBgjGhnLBn2Kaau9", //nolint:lll
   219  		},
   220  		{
   221  			name:     "test P-521",
   222  			kty:      "EC",
   223  			curve:    elliptic.P521(),
   224  			x:        "ASUHPMyichQ0QbHZ9ofNx_l4y7luncn5feKLo3OpJ2nSbZoC7mffolj5uy7s6KSKXFmnNWxGJ42IOrjZ47qqwqyS",
   225  			y:        "AW9ziIC4ZQQVSNmLlp59yYKrjRY0_VqO-GOIYQ9tYpPraBKUloEId6cI_vynCzlZWZtWpgOM3HPhYEgawQ703RjC",
   226  			DIDKey:   "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7",
   227  			DIDKeyID: "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7", //nolint:lll
   228  		},
   229  		{
   230  			name:     "test EC with invalid curve",
   231  			kty:      "EC",
   232  			curve:    &elliptic.CurveParams{},
   233  			x:        "ASUHPMyichQ0QbHZ9ofNx_l4y7luncn5feKLo3OpJ2nSbZoC7mffolj5uy7s6KSKXFmnNWxGJ42IOrjZ47qqwqyS",
   234  			y:        "AW9ziIC4ZQQVSNmLlp59yYKrjRY0_VqO-GOIYQ9tYpPraBKUloEId6cI_vynCzlZWZtWpgOM3HPhYEgawQ703RjC",
   235  			DIDKey:   "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7",
   236  			DIDKeyID: "did:key:z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7#z2J9gaYxrKVpdoG9A4gRnmpnRCcxU6agDtFVVBVdn1JedouoZN7SzcyREXXzWgt3gGiwpoHq7K68X4m32D8HgzG8wv3sY5j7", //nolint:lll
   237  		},
   238  	}
   239  
   240  	for _, test := range tests {
   241  		tc := test
   242  
   243  		var (
   244  			jwkKey *jwk.JWK
   245  			err    error
   246  		)
   247  
   248  		t.Run(tc.name+" CreateDIDKeyByJwk", func(t *testing.T) {
   249  			switch tc.name {
   250  			case "test Ed25519":
   251  				edKey := ed25519.PublicKey(base58.Decode(tc.valB58))
   252  				jwkKey, err = jwksupport.JWKFromKey(edKey)
   253  				require.NoError(t, err)
   254  			case "test X25519":
   255  				jwkKey, err = jwksupport.JWKFromX25519Key(base58.Decode(tc.valB58))
   256  				require.NoError(t, err)
   257  			default:
   258  				x := readBigInt(t, tc.x)
   259  				y := readBigInt(t, tc.y)
   260  				publicKey := ecdsa.PublicKey{
   261  					Curve: tc.curve,
   262  					X:     x,
   263  					Y:     y,
   264  				}
   265  
   266  				jwkKey, err = jwksupport.JWKFromKey(&publicKey)
   267  
   268  				if tc.name == "test EC with invalid curve" {
   269  					require.EqualError(t, err, "create JWK: go-jose/go-jose: unsupported/unknown elliptic curve")
   270  					jwkKey = &jwk.JWK{
   271  						JSONWebKey: jose.JSONWebKey{},
   272  						Kty:        "EC",
   273  						Crv:        "invalid",
   274  					}
   275  				} else {
   276  					require.NoError(t, err)
   277  				}
   278  			}
   279  
   280  			didKey, keyID, err := CreateDIDKeyByJwk(jwkKey)
   281  
   282  			if tc.name == "test EC with invalid curve" {
   283  				require.EqualError(t, err, "unsupported crv invalid")
   284  				return
   285  			}
   286  
   287  			require.NoError(t, err)
   288  			require.Equal(t, tc.DIDKey, didKey)
   289  			require.Equal(t, tc.DIDKeyID, keyID)
   290  		})
   291  	}
   292  
   293  	t.Run("nil input", func(t *testing.T) {
   294  		_, _, err := CreateDIDKeyByJwk(nil)
   295  		require.Error(t, err)
   296  		require.Contains(t, err.Error(), "jsonWebKey is required")
   297  	})
   298  
   299  	t.Run("test invalid type", func(t *testing.T) {
   300  		jwkKey := jwk.JWK{
   301  			Kty: "XX",
   302  			Crv: elliptic.P256().Params().Name,
   303  		}
   304  		_, _, err := CreateDIDKeyByJwk(&jwkKey)
   305  		require.Error(t, err)
   306  		require.Contains(t, err.Error(), "unsupported kty")
   307  	})
   308  }
   309  
   310  func TestRSAFingerprint(t *testing.T) {
   311  	testKeys := []struct {
   312  		bitCount       int
   313  		expectedPrefix string
   314  	}{
   315  		{
   316  			bitCount:       2048,
   317  			expectedPrefix: "did:key:z4MX",
   318  		},
   319  		{
   320  			bitCount:       4096,
   321  			expectedPrefix: "did:key:zgg",
   322  		},
   323  	}
   324  
   325  	for _, testKey := range testKeys {
   326  		t.Run(fmt.Sprint("RSA-", testKey.bitCount), func(t *testing.T) {
   327  			key, err := rsa.GenerateKey(rand.Reader, testKey.bitCount)
   328  			require.NoError(t, err)
   329  
   330  			jwkKey, err := jwksupport.JWKFromKey(&key.PublicKey)
   331  			require.NoError(t, err)
   332  
   333  			didKey, keyID, err := CreateDIDKeyByJwk(jwkKey)
   334  			require.NoError(t, err)
   335  
   336  			assert.NotEmpty(t, didKey)
   337  			assert.NotEmpty(t, keyID)
   338  			assert.True(t, strings.HasPrefix(didKey, testKey.expectedPrefix))
   339  		})
   340  	}
   341  }
   342  
   343  func TestRSAInvalidKey(t *testing.T) {
   344  	key, err := rsa.GenerateKey(rand.Reader, 2048)
   345  	require.NoError(t, err)
   346  
   347  	jwkKey, err := jwksupport.JWKFromKey(&key.PublicKey)
   348  	require.NoError(t, err)
   349  
   350  	jwkKey.Key = "invalid key type"
   351  	didKey, keyID, err := CreateDIDKeyByJwk(jwkKey)
   352  	require.Empty(t, didKey)
   353  	require.Empty(t, keyID)
   354  	require.ErrorContains(t, err, "unexpected RSA key type string")
   355  }
   356  
   357  func TestDIDKeyEd25519(t *testing.T) {
   358  	const (
   359  		k1       = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH"
   360  		k1Base58 = "B12NYF8RrR3h41TDCTJojY59usg3mbtbjnFs7Eud1Y6u"
   361  		k1KeyID  = "did:key:z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH#z6MkpTHR8VNsBxYAAWHut2Geadd9jSwuBV8xRoAnwWsdvktH" //nolint:lll
   362  	)
   363  
   364  	didKey, keyID := CreateDIDKey(base58.Decode(k1Base58))
   365  
   366  	require.Equal(t, didKey, k1)
   367  	require.Equal(t, keyID, k1KeyID)
   368  
   369  	pubKey, err := PubKeyFromDIDKey(k1)
   370  	require.Equal(t, k1Base58, base58.Encode(pubKey))
   371  	require.NoError(t, err)
   372  }
   373  
   374  func TestDIDKeyX25519(t *testing.T) {
   375  	const (
   376  		x25519DIDKey = "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F"
   377  		x25519Base58 = "4Dy8E9UaZscuPUf2GLxV44RCNL7oxmEXXkgWXaug1WKV"
   378  		keyIDX25519  = "did:key:z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F#z6LSeu9HkTHSfLLeUs2nnzUSNedgDUevfNQgQjQC23ZCit6F" //nolint:lll
   379  	)
   380  
   381  	didKey, keyID := CreateDIDKeyByCode(X25519PubKeyMultiCodec, base58.Decode(x25519Base58))
   382  
   383  	require.Equal(t, x25519DIDKey, didKey)
   384  	require.Equal(t, keyID, keyIDX25519)
   385  
   386  	pubKey, err := PubKeyFromDIDKey(x25519DIDKey)
   387  	require.NoError(t, err)
   388  	require.Equal(t, x25519Base58, base58.Encode(pubKey))
   389  }
   390  
   391  func TestPubKeyFromDIDKeyFailure(t *testing.T) {
   392  	_, err := PubKeyFromDIDKey("did:key:****")
   393  	require.EqualError(t, err, "pubKeyFromDIDKey: MethodIDFromDIDKey: not a valid did:key identifier "+
   394  		"(not a base58btc multicodec): did:key:****")
   395  }