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 }