github.com/hashgraph/hedera-sdk-go/v2@v2.48.0/ed25519_public_key.go (about)

     1  package hedera
     2  
     3  /*-
     4   *
     5   * Hedera Go SDK
     6   *
     7   * Copyright (C) 2020 - 2024 Hedera Hashgraph, LLC
     8   *
     9   * Licensed under the Apache License, Version 2.0 (the "License");
    10   * you may not use this file except in compliance with the License.
    11   * You may obtain a copy of the License at
    12   *
    13   *      http://www.apache.org/licenses/LICENSE-2.0
    14   *
    15   * Unless required by applicable law or agreed to in writing, software
    16   * distributed under the License is distributed on an "AS IS" BASIS,
    17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    18   * See the License for the specific language governing permissions and
    19   * limitations under the License.
    20   *
    21   */
    22  
    23  import (
    24  	"bytes"
    25  	"crypto/ed25519"
    26  	"crypto/x509/pkix"
    27  	"encoding/asn1"
    28  	"encoding/hex"
    29  
    30  	"github.com/hashgraph/hedera-protobufs-go/services"
    31  	"github.com/pkg/errors"
    32  )
    33  
    34  // _Ed25519PublicKey is an ed25519 public key.
    35  type _Ed25519PublicKey struct {
    36  	keyData []byte
    37  }
    38  
    39  // PublicKeyFromString recovers an _Ed25519PublicKey from its text-encoded representation.
    40  func _Ed25519PublicKeyFromString(s string) (*_Ed25519PublicKey, error) {
    41  	byt, err := hex.DecodeString(s)
    42  	if err != nil {
    43  		return &_Ed25519PublicKey{}, err
    44  	}
    45  
    46  	return _Ed25519PublicKeyFromBytes(byt)
    47  }
    48  
    49  // _Ed25519PublicKeyFromBytes constructs a known _Ed25519PublicKey from its text-encoded representation.
    50  func _Ed25519PublicKeyFromBytes(bytes []byte) (*_Ed25519PublicKey, error) {
    51  	length := len(bytes)
    52  	switch length {
    53  	case 32:
    54  		return _Ed25519PublicKeyFromBytesRaw(bytes)
    55  	case 44:
    56  		return _Ed25519PublicKeyFromBytesDer(bytes)
    57  	default:
    58  		return &_Ed25519PublicKey{}, _NewErrBadKeyf("invalid public key length: %v bytes", len(bytes))
    59  	}
    60  }
    61  
    62  // _Ed25519PublicKeyFromBytes constructs a known _Ed25519PublicKey from its text-encoded representation.
    63  func _Ed25519PublicKeyFromBytesRaw(bytes []byte) (*_Ed25519PublicKey, error) {
    64  	if bytes == nil {
    65  		return &_Ed25519PublicKey{}, errByteArrayNull
    66  	}
    67  	if len(bytes) != ed25519.PublicKeySize {
    68  		return &_Ed25519PublicKey{}, _NewErrBadKeyf("invalid public key length: %v bytes", len(bytes))
    69  	}
    70  
    71  	return &_Ed25519PublicKey{
    72  		keyData: bytes,
    73  	}, nil
    74  }
    75  
    76  func _Ed25519PublicKeyFromBytesDer(bytes []byte) (*_Ed25519PublicKey, error) {
    77  	ed25519OID := asn1.ObjectIdentifier{1, 3, 101, 112}
    78  
    79  	publicKeyInfo := struct {
    80  		Algorithm pkix.AlgorithmIdentifier
    81  		PublicKey asn1.BitString
    82  	}{}
    83  
    84  	_, err := asn1.Unmarshal(bytes, &publicKeyInfo)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	if !publicKeyInfo.Algorithm.Algorithm.Equal(ed25519OID) {
    90  		return nil, errors.New("invalid algorithm identifier, expected Ed25519")
    91  	}
    92  
    93  	if len(publicKeyInfo.PublicKey.Bytes) != 32 {
    94  		return nil, errors.New("invalid public key length, expected 32 bytes")
    95  	}
    96  
    97  	var pk _Ed25519PublicKey
    98  	pk.keyData = publicKeyInfo.PublicKey.Bytes
    99  
   100  	return &pk, nil
   101  }
   102  
   103  func (pk _Ed25519PublicKey) _StringDer() string {
   104  	return hex.EncodeToString(pk._BytesDer())
   105  }
   106  
   107  // String returns the text-encoded representation of the _Ed25519PublicKey.
   108  func (pk _Ed25519PublicKey) _StringRaw() string {
   109  	return hex.EncodeToString(pk.keyData)
   110  }
   111  
   112  // _Bytes returns the byte slice representation of the _Ed25519PublicKey.
   113  func (pk _Ed25519PublicKey) _Bytes() []byte {
   114  	return pk.keyData
   115  }
   116  
   117  // _Bytes returns the byte slice representation of the _Ed25519PublicKey.
   118  func (pk _Ed25519PublicKey) _BytesRaw() []byte {
   119  	return pk.keyData
   120  }
   121  
   122  func (pk _Ed25519PublicKey) _BytesDer() []byte {
   123  	type PublicKeyInfo struct {
   124  		Algorithm pkix.AlgorithmIdentifier
   125  		PublicKey asn1.BitString
   126  	}
   127  
   128  	ed25519OID := asn1.ObjectIdentifier{1, 3, 101, 112}
   129  	publicKeyInfo := PublicKeyInfo{
   130  		Algorithm: pkix.AlgorithmIdentifier{
   131  			Algorithm: ed25519OID,
   132  		},
   133  		PublicKey: asn1.BitString{
   134  			Bytes:     pk.keyData,
   135  			BitLength: len(pk.keyData) * 8,
   136  		},
   137  	}
   138  
   139  	derBytes, err := asn1.Marshal(publicKeyInfo)
   140  	if err != nil {
   141  		return nil
   142  	}
   143  
   144  	return derBytes
   145  }
   146  
   147  func (pk _Ed25519PublicKey) _ToProtoKey() *services.Key {
   148  	return &services.Key{Key: &services.Key_Ed25519{Ed25519: pk.keyData}}
   149  }
   150  
   151  func (pk _Ed25519PublicKey) String() string {
   152  	return pk._StringRaw()
   153  }
   154  
   155  func (pk _Ed25519PublicKey) _ToSignaturePairProtobuf(signature []byte) *services.SignaturePair {
   156  	return &services.SignaturePair{
   157  		PubKeyPrefix: pk.keyData,
   158  		Signature: &services.SignaturePair_Ed25519{
   159  			Ed25519: signature,
   160  		},
   161  	}
   162  }
   163  
   164  func (pk _Ed25519PublicKey) _Verify(message []byte, signature []byte) bool {
   165  	return ed25519.Verify(pk._Bytes(), message, signature)
   166  }
   167  
   168  func (pk _Ed25519PublicKey) _VerifyTransaction(tx Transaction) bool {
   169  	if tx.signedTransactions._Length() == 0 {
   170  		return false
   171  	}
   172  
   173  	_, _ = tx._BuildAllTransactions()
   174  
   175  	for _, value := range tx.signedTransactions.slice {
   176  		tx := value.(*services.SignedTransaction)
   177  		found := false
   178  		for _, sigPair := range tx.SigMap.GetSigPair() {
   179  			if bytes.Equal(sigPair.GetPubKeyPrefix(), pk._Bytes()) {
   180  				found = true
   181  				if !pk._Verify(tx.BodyBytes, sigPair.GetEd25519()) {
   182  					return false
   183  				}
   184  			}
   185  		}
   186  
   187  		if !found {
   188  			return false
   189  		}
   190  	}
   191  
   192  	return true
   193  }