github.com/trustbloc/kms-go@v1.1.2/util/cryptoutil/utils.go (about)

     1  /*
     2  Copyright SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package cryptoutil
     8  
     9  import (
    10  	"crypto/ed25519"
    11  	"encoding/binary"
    12  	"errors"
    13  	"fmt"
    14  
    15  	"github.com/teserakt-io/golang-ed25519/extra25519"
    16  	chacha "golang.org/x/crypto/chacha20poly1305"
    17  	"golang.org/x/crypto/curve25519"
    18  )
    19  
    20  // DeriveECDHX25519 does X25519 ECDH using fromPrivKey and toPubKey.
    21  func DeriveECDHX25519(fromPrivKey, toPubKey *[chacha.KeySize]byte) ([]byte, error) {
    22  	if fromPrivKey == nil || toPubKey == nil {
    23  		return nil, errors.New("deriveECDHX25519: invalid key")
    24  	}
    25  
    26  	// do ScalarMult of the sender's private key with the recipient key to get a derived Z point (ECDH)
    27  	z, err := curve25519.X25519(fromPrivKey[:], toPubKey[:])
    28  	if err != nil {
    29  		return nil, fmt.Errorf("deriveECDHX25519: %w", err)
    30  	}
    31  
    32  	return z, nil
    33  }
    34  
    35  // LengthPrefix array with a bigEndian uint32 value of array's length.
    36  func LengthPrefix(array []byte) []byte {
    37  	const prefixLen = 4
    38  
    39  	arrInfo := make([]byte, prefixLen+len(array))
    40  	binary.BigEndian.PutUint32(arrInfo, uint32(len(array)))
    41  	copy(arrInfo[prefixLen:], array)
    42  
    43  	return arrInfo
    44  }
    45  
    46  // Curve25519KeySize number of bytes in a Curve25519 public or private key.
    47  const Curve25519KeySize = 32
    48  
    49  // NonceSize size of a nonce used by Box encryption (Xchacha20Poly1305).
    50  const NonceSize = 24
    51  
    52  // PublicEd25519toCurve25519 takes an Ed25519 public key and provides the corresponding Curve25519 public key
    53  // This function wraps PublicKeyToCurve25519 from Adam Langley's ed25519 repo: https://github.com/agl/ed25519 now
    54  // moved to https://github.com/teserakt-io/golang-ed25519
    55  func PublicEd25519toCurve25519(pub []byte) ([]byte, error) {
    56  	if len(pub) == 0 {
    57  		return nil, errors.New("public key is nil")
    58  	}
    59  
    60  	if len(pub) != ed25519.PublicKeySize {
    61  		return nil, fmt.Errorf("%d-byte key size is invalid", len(pub))
    62  	}
    63  
    64  	pkOut := new([Curve25519KeySize]byte)
    65  	pKIn := new([Curve25519KeySize]byte)
    66  	copy(pKIn[:], pub)
    67  
    68  	success := extra25519.PublicKeyToCurve25519(pkOut, pKIn)
    69  	if !success {
    70  		return nil, errors.New("error converting public key")
    71  	}
    72  
    73  	return pkOut[:], nil
    74  }
    75  
    76  // SecretEd25519toCurve25519 converts a secret key from Ed25519 to curve25519 format
    77  // This function wraps PrivateKeyToCurve25519 from Adam Langley's ed25519 repo: https://github.com/agl/ed25519 now
    78  // moved to https://github.com/teserakt-io/golang-ed25519
    79  func SecretEd25519toCurve25519(priv []byte) ([]byte, error) {
    80  	if len(priv) == 0 {
    81  		return nil, errors.New("private key is nil")
    82  	}
    83  
    84  	sKIn := new([ed25519.PrivateKeySize]byte)
    85  	copy(sKIn[:], priv)
    86  
    87  	sKOut := new([Curve25519KeySize]byte)
    88  	extra25519.PrivateKeyToCurve25519(sKOut, sKIn)
    89  
    90  	return sKOut[:], nil
    91  }