github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/p2p/key.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package p2p
    19  
    20  import (
    21  	"crypto/rand"
    22  	"encoding/hex"
    23  	"errors"
    24  	"fmt"
    25  	"io"
    26  
    27  	"golang.org/x/crypto/nacl/box"
    28  )
    29  
    30  const keySize = 32
    31  
    32  // PublicKey represents p2p public key part.
    33  type PublicKey [keySize]byte
    34  
    35  // Hex returns public encoded as in hex string.
    36  func (k *PublicKey) Hex() string {
    37  	return hex.EncodeToString(k[:])
    38  }
    39  
    40  // DecodePublicKey converts hex string to PublicKey.
    41  func DecodePublicKey(keyHex string) (PublicKey, error) {
    42  	key := [keySize]byte{}
    43  	src, err := hex.DecodeString(keyHex)
    44  	if err != nil {
    45  		return key, fmt.Errorf("could not decode key from hex: %w", err)
    46  	}
    47  	if len(src) != keySize {
    48  		return key, fmt.Errorf("key size is invalid, expect %d, got %d", keySize, len(src))
    49  	}
    50  	copy(key[:], src)
    51  	return key, nil
    52  }
    53  
    54  // PrivateKey represents p2p private key.
    55  type PrivateKey [32]byte
    56  
    57  // Encrypt encrypts data using nacl as underlying crypt system.
    58  func (k *PrivateKey) Encrypt(publicKey PublicKey, src []byte) ([]byte, error) {
    59  	var nonce [24]byte
    60  	if _, err := io.ReadFull(rand.Reader, nonce[:]); err != nil {
    61  		return nil, fmt.Errorf("could not read random nonce: %w", err)
    62  	}
    63  	return box.Seal(nonce[:], src, &nonce, (*[32]byte)(&publicKey), (*[32]byte)(k)), nil
    64  }
    65  
    66  // Decrypt decrypts data using nacl as underlying crypt system.
    67  func (k *PrivateKey) Decrypt(publicKey PublicKey, ciphertext []byte) ([]byte, error) {
    68  	var decryptNonce [24]byte
    69  	copy(decryptNonce[:], ciphertext[:24])
    70  	decrypted, ok := box.Open(nil, ciphertext[24:], &decryptNonce, (*[32]byte)(&publicKey), (*[32]byte)(k))
    71  	if !ok {
    72  		return nil, errors.New("could not decrypt message")
    73  	}
    74  	return decrypted, nil
    75  }
    76  
    77  // GenerateKey generates p2p public and private key pairs.
    78  func GenerateKey() (PublicKey, PrivateKey, error) {
    79  	publicKey := [keySize]byte{}
    80  	privateKey := [keySize]byte{}
    81  	pub, priv, err := box.GenerateKey(rand.Reader)
    82  	if err != nil {
    83  		return PublicKey{}, PrivateKey{}, fmt.Errorf("could not generate public private key pairs: %w", err)
    84  	}
    85  	copy(publicKey[:], pub[:])
    86  	copy(privateKey[:], priv[:])
    87  	return publicKey, privateKey, nil
    88  }