2022-09-12 08:31:02 +00:00
|
|
|
// Package keys_and_cert implements the I2P KeysAndCert common data structure
|
2022-07-11 23:41:58 -04:00
|
|
|
package keys_and_cert
|
2016-02-01 01:56:10 -08:00
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
import (
|
2024-11-24 14:25:40 -05:00
|
|
|
"encoding/binary"
|
2022-09-12 08:31:02 +00:00
|
|
|
"errors"
|
2024-11-18 12:25:31 -05:00
|
|
|
"fmt"
|
2024-10-18 13:22:36 -04:00
|
|
|
|
2024-10-18 12:41:48 -04:00
|
|
|
"github.com/go-i2p/go-i2p/lib/util/logger"
|
2022-09-12 08:31:02 +00:00
|
|
|
|
|
|
|
. "github.com/go-i2p/go-i2p/lib/common/certificate"
|
|
|
|
. "github.com/go-i2p/go-i2p/lib/common/key_certificate"
|
|
|
|
"github.com/go-i2p/go-i2p/lib/crypto"
|
2024-10-18 12:41:48 -04:00
|
|
|
"github.com/sirupsen/logrus"
|
2022-09-12 08:31:02 +00:00
|
|
|
)
|
|
|
|
|
2024-10-23 00:06:06 -04:00
|
|
|
var log = logger.GetGoI2PLogger()
|
2024-10-18 12:41:48 -04:00
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// Sizes of various KeysAndCert structures and requirements
|
|
|
|
const (
|
|
|
|
KEYS_AND_CERT_PUBKEY_SIZE = 256
|
|
|
|
KEYS_AND_CERT_SPK_SIZE = 128
|
|
|
|
KEYS_AND_CERT_MIN_SIZE = 387
|
|
|
|
KEYS_AND_CERT_DATA_SIZE = 384
|
|
|
|
)
|
|
|
|
|
2024-11-24 14:25:40 -05:00
|
|
|
// Key sizes in bytes
|
|
|
|
|
2016-02-16 01:04:40 -08:00
|
|
|
/*
|
2022-09-12 08:31:02 +00:00
|
|
|
[KeysAndCert]
|
|
|
|
Accurate for version 0.9.49
|
|
|
|
|
|
|
|
Description
|
|
|
|
An encryption public key, a signing public key, and a certificate, used as either a RouterIdentity or a Destination.
|
|
|
|
|
|
|
|
Contents
|
2024-11-09 00:53:17 -05:00
|
|
|
A publicKey followed by a signingPublicKey and then a Certificate.
|
2016-02-16 01:04:40 -08:00
|
|
|
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
| public_key |
|
|
|
|
+ +
|
|
|
|
| |
|
|
|
|
~ ~
|
|
|
|
~ ~
|
|
|
|
| |
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
| padding (optional) |
|
|
|
|
~ ~
|
|
|
|
~ ~
|
|
|
|
| |
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
| signing_key |
|
|
|
|
+ +
|
|
|
|
| |
|
|
|
|
~ ~
|
|
|
|
~ ~
|
|
|
|
| |
|
|
|
|
+----+----+----+----+----+----+----+----+
|
|
|
|
| certificate |
|
|
|
|
+----+----+----+-//
|
|
|
|
|
2024-11-09 00:53:17 -05:00
|
|
|
public_key :: publicKey (partial or full)
|
2016-02-16 01:04:40 -08:00
|
|
|
length -> 256 bytes or as specified in key certificate
|
|
|
|
|
|
|
|
padding :: random data
|
|
|
|
length -> 0 bytes or as specified in key certificate
|
2022-09-12 08:31:02 +00:00
|
|
|
padding length + signing_key length == 128 bytes
|
2016-02-16 01:04:40 -08:00
|
|
|
|
2024-11-09 00:53:17 -05:00
|
|
|
signing__key :: signingPublicKey (partial or full)
|
2016-02-16 01:04:40 -08:00
|
|
|
length -> 128 bytes or as specified in key certificate
|
2022-09-12 08:31:02 +00:00
|
|
|
padding length + signing_key length == 128 bytes
|
2016-02-16 01:04:40 -08:00
|
|
|
|
|
|
|
certificate :: Certificate
|
|
|
|
length -> >= 3 bytes
|
|
|
|
|
|
|
|
total length: 387+ bytes
|
|
|
|
*/
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// KeysAndCert is the represenation of an I2P KeysAndCert.
|
|
|
|
//
|
|
|
|
// https://geti2p.net/spec/common-structures#keysandcert
|
2022-05-09 20:43:24 -04:00
|
|
|
type KeysAndCert struct {
|
2024-11-09 00:53:17 -05:00
|
|
|
keyCertificate *KeyCertificate
|
2022-05-09 20:43:24 -04:00
|
|
|
publicKey crypto.PublicKey
|
2024-11-09 00:53:17 -05:00
|
|
|
Padding []byte
|
2022-05-09 20:43:24 -04:00
|
|
|
signingPublicKey crypto.SigningPublicKey
|
|
|
|
}
|
2016-02-05 02:23:11 -08:00
|
|
|
|
2024-11-09 00:53:17 -05:00
|
|
|
// Bytes returns the entire keyCertificate in []byte form, trims payload to specified length.
|
2024-10-03 21:31:54 -04:00
|
|
|
func (keys_and_cert KeysAndCert) Bytes() []byte {
|
2024-11-15 11:30:59 -05:00
|
|
|
bytes := keys_and_cert.publicKey.Bytes()
|
2024-11-10 17:15:56 -05:00
|
|
|
bytes = append(bytes, keys_and_cert.Padding...)
|
|
|
|
bytes = append(bytes, keys_and_cert.signingPublicKey.Bytes()...)
|
2024-11-15 11:30:59 -05:00
|
|
|
bytes = append(bytes, keys_and_cert.keyCertificate.Bytes()...)
|
2024-11-10 19:29:07 -05:00
|
|
|
log.WithFields(logrus.Fields{
|
2024-11-15 11:30:59 -05:00
|
|
|
"bytes_length": len(bytes),
|
|
|
|
"pk_bytes_length": len(keys_and_cert.publicKey.Bytes()),
|
2024-11-10 19:29:07 -05:00
|
|
|
"padding_bytes_length": len(keys_and_cert.Padding),
|
2024-11-15 11:30:59 -05:00
|
|
|
"spk_bytes_length": len(keys_and_cert.signingPublicKey.Bytes()),
|
|
|
|
"cert_bytes_length": len(keys_and_cert.keyCertificate.Bytes()),
|
2024-11-10 19:29:07 -05:00
|
|
|
}).Debug("Retrieved bytes from KeysAndCert")
|
2024-10-18 12:41:48 -04:00
|
|
|
return bytes
|
2022-08-01 12:50:42 -04:00
|
|
|
}
|
|
|
|
|
2024-11-09 00:53:17 -05:00
|
|
|
// publicKey returns the public key as a crypto.publicKey.
|
2022-05-09 20:43:24 -04:00
|
|
|
func (keys_and_cert *KeysAndCert) PublicKey() (key crypto.PublicKey) {
|
|
|
|
return keys_and_cert.publicKey
|
2016-02-05 02:23:11 -08:00
|
|
|
}
|
|
|
|
|
2024-11-09 00:53:17 -05:00
|
|
|
// signingPublicKey returns the signing public key.
|
2022-05-09 20:43:24 -04:00
|
|
|
func (keys_and_cert *KeysAndCert) SigningPublicKey() (signing_public_key crypto.SigningPublicKey) {
|
|
|
|
return keys_and_cert.signingPublicKey
|
2016-02-05 02:23:11 -08:00
|
|
|
}
|
|
|
|
|
2022-09-12 08:31:02 +00:00
|
|
|
// Certfificate returns the certificate.
|
2024-10-03 21:31:54 -04:00
|
|
|
func (keys_and_cert *KeysAndCert) Certificate() (cert Certificate) {
|
2024-11-09 00:53:17 -05:00
|
|
|
return keys_and_cert.keyCertificate.Certificate
|
2016-02-05 02:23:11 -08:00
|
|
|
}
|
|
|
|
|
2024-10-03 21:31:54 -04:00
|
|
|
// ReadKeysAndCert creates a new *KeysAndCert from []byte using ReadKeysAndCert.
|
|
|
|
// Returns a pointer to KeysAndCert unlike ReadKeysAndCert.
|
2016-02-13 21:00:29 -08:00
|
|
|
func ReadKeysAndCert(data []byte) (keys_and_cert KeysAndCert, remainder []byte, err error) {
|
2024-10-18 12:41:48 -04:00
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"input_length": len(data),
|
|
|
|
}).Debug("Reading KeysAndCert from data")
|
|
|
|
|
2024-10-03 21:31:54 -04:00
|
|
|
data_len := len(data)
|
2024-11-18 12:25:31 -05:00
|
|
|
if data_len < KEYS_AND_CERT_MIN_SIZE {
|
2024-10-18 12:41:48 -04:00
|
|
|
log.WithFields(logrus.Fields{
|
2022-05-09 20:43:24 -04:00
|
|
|
"at": "ReadKeysAndCert",
|
|
|
|
"data_len": data_len,
|
|
|
|
"required_len": KEYS_AND_CERT_MIN_SIZE,
|
|
|
|
"reason": "not enough data",
|
|
|
|
}).Error("error parsing keys and cert")
|
|
|
|
err = errors.New("error parsing KeysAndCert: data is smaller than minimum valid size")
|
|
|
|
return
|
|
|
|
}
|
2024-11-18 12:25:31 -05:00
|
|
|
|
2024-11-09 00:53:17 -05:00
|
|
|
keys_and_cert.keyCertificate, remainder, err = NewKeyCertificate(data[KEYS_AND_CERT_DATA_SIZE:])
|
2022-05-09 20:43:24 -04:00
|
|
|
if err != nil {
|
2024-11-09 00:53:17 -05:00
|
|
|
log.WithError(err).Error("Failed to create keyCertificate")
|
2024-10-03 21:31:54 -04:00
|
|
|
return
|
2022-05-09 20:43:24 -04:00
|
|
|
}
|
2024-11-18 12:25:31 -05:00
|
|
|
|
|
|
|
// Get the actual key sizes from the certificate
|
|
|
|
pubKeySize := keys_and_cert.keyCertificate.CryptoSize()
|
|
|
|
sigKeySize := keys_and_cert.keyCertificate.SignatureSize()
|
|
|
|
|
|
|
|
// Construct public key
|
|
|
|
keys_and_cert.publicKey, err = keys_and_cert.keyCertificate.ConstructPublicKey(data[:pubKeySize])
|
2022-05-09 20:43:24 -04:00
|
|
|
if err != nil {
|
2024-11-09 00:53:17 -05:00
|
|
|
log.WithError(err).Error("Failed to construct publicKey")
|
2024-10-03 21:31:54 -04:00
|
|
|
return
|
2022-05-09 20:43:24 -04:00
|
|
|
}
|
2024-11-18 12:25:31 -05:00
|
|
|
|
|
|
|
// Calculate padding size and extract padding
|
|
|
|
paddingSize := KEYS_AND_CERT_DATA_SIZE - pubKeySize - sigKeySize
|
|
|
|
if paddingSize > 0 {
|
|
|
|
keys_and_cert.Padding = make([]byte, paddingSize)
|
|
|
|
copy(keys_and_cert.Padding, data[pubKeySize:pubKeySize+paddingSize])
|
|
|
|
}
|
|
|
|
|
|
|
|
// Construct signing public key
|
|
|
|
keys_and_cert.signingPublicKey, err = keys_and_cert.keyCertificate.ConstructSigningPublicKey(
|
|
|
|
data[KEYS_AND_CERT_DATA_SIZE-sigKeySize : KEYS_AND_CERT_DATA_SIZE],
|
|
|
|
)
|
2022-05-09 20:43:24 -04:00
|
|
|
if err != nil {
|
2024-11-09 00:53:17 -05:00
|
|
|
log.WithError(err).Error("Failed to construct signingPublicKey")
|
2024-10-03 21:31:54 -04:00
|
|
|
return
|
2022-05-09 20:43:24 -04:00
|
|
|
}
|
2024-10-18 12:41:48 -04:00
|
|
|
|
|
|
|
log.WithFields(logrus.Fields{
|
2024-11-09 00:53:17 -05:00
|
|
|
"public_key_type": keys_and_cert.keyCertificate.PublicKeyType(),
|
|
|
|
"signing_public_key_type": keys_and_cert.keyCertificate.SigningPublicKeyType(),
|
2024-11-18 12:25:31 -05:00
|
|
|
"padding_length": len(keys_and_cert.Padding),
|
2024-10-18 12:41:48 -04:00
|
|
|
"remainder_length": len(remainder),
|
|
|
|
}).Debug("Successfully read KeysAndCert")
|
|
|
|
|
2024-10-03 21:31:54 -04:00
|
|
|
return
|
2022-05-09 20:43:24 -04:00
|
|
|
}
|
2024-11-04 19:19:03 -05:00
|
|
|
|
2024-11-23 23:54:01 -05:00
|
|
|
func ReadKeysAndCertElgAndEd25519(data []byte) (keysAndCert *KeysAndCert, remainder []byte, err error) {
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"input_length": len(data),
|
|
|
|
}).Debug("Reading KeysAndCert from data")
|
|
|
|
|
|
|
|
// Constants based on fixed key sizes
|
|
|
|
const (
|
|
|
|
pubKeySize = 256 // ElGamal public key size
|
|
|
|
sigKeySize = 32 // Ed25519 public key size
|
|
|
|
totalKeySize = 384 // KEYS_AND_CERT_DATA_SIZE
|
|
|
|
paddingSize = totalKeySize - pubKeySize - sigKeySize // 96 bytes
|
|
|
|
minDataLength = totalKeySize + 3
|
|
|
|
)
|
|
|
|
|
|
|
|
dataLen := len(data)
|
|
|
|
if dataLen < minDataLength {
|
|
|
|
err = fmt.Errorf("error parsing KeysAndCert: data is smaller than minimum valid size, got %d bytes", dataLen)
|
|
|
|
log.WithError(err).Error("Data is smaller than minimum valid size")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize KeysAndCert
|
|
|
|
keysAndCert = &KeysAndCert{}
|
|
|
|
|
|
|
|
// Extract public key
|
|
|
|
publicKeyData := data[:pubKeySize]
|
|
|
|
if len(publicKeyData) != pubKeySize {
|
|
|
|
err = errors.New("invalid ElGamal public key length")
|
|
|
|
log.WithError(err).Error("Invalid ElGamal public key length")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var elgPublicKey crypto.ElgPublicKey
|
|
|
|
copy(elgPublicKey[:], publicKeyData)
|
|
|
|
keysAndCert.publicKey = elgPublicKey
|
|
|
|
|
|
|
|
// Extract padding
|
|
|
|
paddingStart := pubKeySize
|
|
|
|
paddingEnd := paddingStart + paddingSize
|
|
|
|
keysAndCert.Padding = data[paddingStart:paddingEnd]
|
|
|
|
|
|
|
|
// Extract signing public key
|
|
|
|
signingPubKeyData := data[paddingEnd : paddingEnd+sigKeySize]
|
|
|
|
if len(signingPubKeyData) != sigKeySize {
|
|
|
|
err = errors.New("invalid Ed25519 public key length")
|
|
|
|
log.WithError(err).Error("Invalid Ed25519 public key length")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
edPublicKey := crypto.Ed25519PublicKey(signingPubKeyData)
|
|
|
|
keysAndCert.signingPublicKey = edPublicKey
|
|
|
|
|
|
|
|
// Extract the certificate
|
|
|
|
certData := data[totalKeySize:]
|
|
|
|
keysAndCert.keyCertificate, remainder, err = NewKeyCertificate(certData)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to read keyCertificate")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"public_key_type": "ElGamal",
|
|
|
|
"signing_public_key_type": "Ed25519",
|
|
|
|
"padding_length": len(keysAndCert.Padding),
|
|
|
|
"remainder_length": len(remainder),
|
|
|
|
}).Debug("Successfully read KeysAndCert")
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-11-24 14:25:40 -05:00
|
|
|
func ReadKeysAndCertDeux(data []byte) (keysAndCert *KeysAndCert, remainder []byte, err error) {
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"input_length": len(data),
|
|
|
|
}).Debug("Reading KeysAndCert from data")
|
|
|
|
|
|
|
|
dataLen := len(data)
|
|
|
|
if dataLen < CERT_MIN_SIZE {
|
|
|
|
err = errors.New("data is too short to contain a certificate")
|
|
|
|
log.WithError(err).Error("Data is too short to contain a certificate")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read the certificate from the end
|
|
|
|
cert, certStartIndex, err := readCertificateFromEnd(data)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to read Certificate")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"cert_type": cert.Type(),
|
|
|
|
}).Debug("Certificate type read")
|
|
|
|
|
|
|
|
// Check if the certificate is of type CERT_KEY
|
|
|
|
if cert.Type() != CERT_KEY {
|
|
|
|
err = fmt.Errorf("unsupported certificate type: %d", cert.Type())
|
|
|
|
log.WithError(err).Error("Unsupported certificate type")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the Key Certificate from the certificate payload
|
|
|
|
keyCert, err := NewKeyCertificateFromCertificate(cert)
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to parse KeyCertificate")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get key sizes
|
|
|
|
pubKeySize, err := keyCert.CryptoPublicKeySize()
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to get crypto public key size")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
sigKeySize, err := keyCert.SigningPublicKeySize()
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to get signing public key size")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Calculate positions
|
|
|
|
signingKeyEndIndex := certStartIndex
|
|
|
|
signingKeyStartIndex := signingKeyEndIndex - sigKeySize
|
|
|
|
paddingEndIndex := signingKeyStartIndex
|
|
|
|
paddingStartIndex := pubKeySize
|
|
|
|
paddingSize := paddingEndIndex - paddingStartIndex
|
|
|
|
|
|
|
|
// Validate positions
|
|
|
|
if signingKeyStartIndex < 0 || paddingStartIndex < 0 || paddingSize < 0 {
|
|
|
|
err = errors.New("error parsing KeysAndCert: invalid key sizes or data too short")
|
|
|
|
log.WithError(err).Error("Invalid key sizes or data too short")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
keysAndCert = &KeysAndCert{
|
|
|
|
keyCertificate: keyCert,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract public key
|
|
|
|
publicKeyData := data[:pubKeySize]
|
|
|
|
keysAndCert.publicKey, err = constructPublicKey(publicKeyData, uint16(keyCert.CpkType.Int()))
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to construct public key")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract padding
|
|
|
|
if paddingSize > 0 {
|
|
|
|
keysAndCert.Padding = data[paddingStartIndex:paddingEndIndex]
|
|
|
|
} else {
|
|
|
|
keysAndCert.Padding = []byte{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract signing public key
|
|
|
|
signingPubKeyData := data[signingKeyStartIndex:signingKeyEndIndex]
|
|
|
|
keysAndCert.signingPublicKey, err = constructSigningPublicKey(signingPubKeyData, uint16(keyCert.SpkType.Int()))
|
|
|
|
if err != nil {
|
|
|
|
log.WithError(err).Error("Failed to construct signing public key")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set remainder to any data before the KeysAndCert
|
|
|
|
totalCertLen := 1 + 2 + cert.Length() // type (1 byte) + length (2 bytes) + payload
|
|
|
|
|
|
|
|
/*
|
|
|
|
Set remainder to any data after the KeysAndCert
|
|
|
|
Since certStartIndex is the index where the certificate starts,
|
|
|
|
certStartIndex + totalCertLen should equal dataLen if there's no extra data.
|
|
|
|
If there's extra data after the certificate, remainder will contain it.
|
|
|
|
*/
|
|
|
|
remainderIndex := certStartIndex + totalCertLen
|
|
|
|
if remainderIndex < dataLen {
|
|
|
|
remainder = data[remainderIndex:]
|
|
|
|
} else {
|
|
|
|
remainder = []byte{}
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"public_key_type": keyCert.CpkType,
|
|
|
|
"signing_public_key_type": keyCert.SpkType,
|
|
|
|
"padding_length": len(keysAndCert.Padding),
|
|
|
|
"remainder_length": len(remainder),
|
|
|
|
}).Debug("Successfully read KeysAndCert")
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func readCertificateFromEnd(data []byte) (cert Certificate, certStartIndex int, err error) {
|
|
|
|
dataLen := len(data)
|
|
|
|
|
|
|
|
// Minimum certificate size is 3 bytes (type + length)
|
|
|
|
if dataLen < CERT_MIN_SIZE {
|
|
|
|
err = errors.New("data is too short to contain a certificate")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Start from the end and work backwards
|
|
|
|
for certLen := 0; certLen <= dataLen-CERT_MIN_SIZE; certLen++ {
|
|
|
|
totalCertLen := 1 + 2 + certLen
|
|
|
|
certStartIndex = dataLen - totalCertLen
|
|
|
|
if certStartIndex < 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
certTypeIndex := certStartIndex
|
|
|
|
certLenBytesIndex := certStartIndex + 1
|
|
|
|
|
|
|
|
// Ensure we have enough data to read type and length
|
|
|
|
if certLenBytesIndex+2 > dataLen {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract certificate type
|
|
|
|
certType := data[certTypeIndex]
|
|
|
|
|
|
|
|
// Extract certificate length
|
|
|
|
certLenBytes := data[certLenBytesIndex : certLenBytesIndex+2]
|
|
|
|
expectedCertLen := int(binary.BigEndian.Uint16(certLenBytes))
|
|
|
|
|
|
|
|
if expectedCertLen != certLen {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Optionally, check for valid certificate types
|
|
|
|
if certType != CERT_KEY && certType != CERT_NULL && certType != CERT_HASHCASH &&
|
|
|
|
certType != CERT_HIDDEN && certType != CERT_SIGNED && certType != CERT_MULTIPLE {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
certData := data[certStartIndex:dataLen]
|
|
|
|
|
|
|
|
// Attempt to read the certificate
|
|
|
|
cert, _, err = ReadCertificate(certData)
|
|
|
|
if err == nil {
|
|
|
|
// Successfully read certificate
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = errors.New("could not find certificate in data")
|
|
|
|
return
|
|
|
|
}
|
2024-11-26 19:47:17 -05:00
|
|
|
|
2024-11-24 14:25:40 -05:00
|
|
|
func constructPublicKey(data []byte, cryptoType uint16) (crypto.PublicKey, error) {
|
|
|
|
switch cryptoType {
|
|
|
|
case CRYPTO_KEY_TYPE_ELGAMAL:
|
|
|
|
if len(data) != 256 {
|
|
|
|
return nil, errors.New("invalid ElGamal public key length")
|
|
|
|
}
|
|
|
|
var elgPublicKey crypto.ElgPublicKey
|
|
|
|
copy(elgPublicKey[:], data)
|
|
|
|
return elgPublicKey, nil
|
|
|
|
// Handle other crypto types...
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unsupported crypto key type: %d", cryptoType)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func constructSigningPublicKey(data []byte, sigType uint16) (crypto.SigningPublicKey, error) {
|
|
|
|
switch sigType {
|
|
|
|
case SIGNATURE_TYPE_ED25519_SHA512:
|
|
|
|
if len(data) != 32 {
|
|
|
|
return nil, errors.New("invalid Ed25519 public key length")
|
|
|
|
}
|
|
|
|
return crypto.Ed25519PublicKey(data), nil
|
|
|
|
// Handle other signature types...
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unsupported signature key type: %d", sigType)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-09 00:53:17 -05:00
|
|
|
// NewKeysAndCert creates a new KeysAndCert instance with the provided parameters.
|
|
|
|
// It validates the sizes of the provided keys and padding before assembling the struct.
|
|
|
|
func NewKeysAndCert(
|
|
|
|
keyCertificate *KeyCertificate,
|
|
|
|
publicKey crypto.PublicKey,
|
|
|
|
padding []byte,
|
|
|
|
signingPublicKey crypto.SigningPublicKey,
|
|
|
|
) (*KeysAndCert, error) {
|
|
|
|
log.Debug("Creating new KeysAndCert with provided parameters")
|
|
|
|
|
|
|
|
if keyCertificate == nil {
|
|
|
|
log.Error("KeyCertificate is nil")
|
|
|
|
return nil, errors.New("KeyCertificate cannot be nil")
|
|
|
|
}
|
|
|
|
|
2024-11-18 12:25:31 -05:00
|
|
|
// Get actual key sizes from certificate
|
|
|
|
pubKeySize := keyCertificate.CryptoSize()
|
|
|
|
sigKeySize := keyCertificate.SignatureSize()
|
|
|
|
|
|
|
|
// Validate public key size
|
|
|
|
if publicKey.Len() != pubKeySize {
|
2024-11-09 00:53:17 -05:00
|
|
|
log.WithFields(logrus.Fields{
|
2024-11-18 12:25:31 -05:00
|
|
|
"expected_size": pubKeySize,
|
2024-11-09 00:53:17 -05:00
|
|
|
"actual_size": publicKey.Len(),
|
|
|
|
}).Error("Invalid publicKey size")
|
2024-11-18 12:25:31 -05:00
|
|
|
return nil, fmt.Errorf("publicKey has invalid size: expected %d, got %d", pubKeySize, publicKey.Len())
|
2024-11-09 00:53:17 -05:00
|
|
|
}
|
|
|
|
|
2024-11-18 12:25:31 -05:00
|
|
|
// Validate signing key size
|
|
|
|
if signingPublicKey.Len() != sigKeySize {
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"expected_size": sigKeySize,
|
|
|
|
"actual_size": signingPublicKey.Len(),
|
|
|
|
}).Error("Invalid signingPublicKey size")
|
|
|
|
return nil, fmt.Errorf("signingPublicKey has invalid size: expected %d, got %d", sigKeySize, signingPublicKey.Len())
|
|
|
|
}
|
2024-11-09 00:53:17 -05:00
|
|
|
|
2024-11-18 12:25:31 -05:00
|
|
|
// Calculate expected padding size
|
|
|
|
expectedPaddingSize := KEYS_AND_CERT_DATA_SIZE - pubKeySize - sigKeySize
|
2024-11-09 00:53:17 -05:00
|
|
|
if len(padding) != expectedPaddingSize {
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"expected_size": expectedPaddingSize,
|
|
|
|
"actual_size": len(padding),
|
2024-11-23 22:45:32 -05:00
|
|
|
}).Error("Invalid padding size")
|
2024-11-24 14:25:40 -05:00
|
|
|
return nil, fmt.Errorf("invalid padding size")
|
2024-11-09 00:53:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
keysAndCert := &KeysAndCert{
|
|
|
|
keyCertificate: keyCertificate,
|
|
|
|
publicKey: publicKey,
|
|
|
|
Padding: padding,
|
|
|
|
signingPublicKey: signingPublicKey,
|
|
|
|
}
|
|
|
|
|
|
|
|
log.WithFields(logrus.Fields{
|
|
|
|
"public_key_length": publicKey.Len(),
|
|
|
|
"signing_public_key_length": signingPublicKey.Len(),
|
|
|
|
"padding_length": len(padding),
|
|
|
|
}).Debug("Successfully created KeysAndCert")
|
|
|
|
|
|
|
|
return keysAndCert, nil
|
|
|
|
}
|