Files
go-i2p/lib/common/key_certificate/key_certificate.go

358 lines
12 KiB
Go
Raw Normal View History

2022-09-12 08:31:02 +00:00
// Package key_certificate implements the I2P Destination common data structure
package key_certificate
2016-02-14 23:10:37 -08:00
/*
I2P Key Certificate
2016-06-16 23:17:21 -07:00
https://geti2p.net/spec/common-structures#certificate
2016-02-14 23:10:37 -08:00
Accurate for version 0.9.24
2016-02-20 19:02:55 -08:00
+----+----+----+----+----+-//
|type| length | payload
+----+----+----+----+----+-//
type :: Integer
length -> 1 byte
case 0 -> NULL
case 1 -> HASHCASH
case 2 -> HIDDEN
case 3 -> SIGNED
case 4 -> MULTIPLE
case 5 -> KEY
length :: Integer
length -> 2 bytes
payload :: data
length -> $length bytes
2016-02-14 23:10:37 -08:00
*/
import (
"errors"
2024-10-18 12:27:42 -04:00
"github.com/go-i2p/go-i2p/lib/util/logger"
"github.com/sirupsen/logrus"
2022-04-27 10:48:59 -04:00
. "github.com/go-i2p/go-i2p/lib/common/certificate"
. "github.com/go-i2p/go-i2p/lib/common/data"
"github.com/go-i2p/go-i2p/lib/crypto"
)
var log = logger.GetGoI2PLogger()
2024-10-18 12:27:42 -04:00
// Key Certificate Signing Key Types
const (
KEYCERT_SIGN_DSA_SHA1 = iota
KEYCERT_SIGN_P256
KEYCERT_SIGN_P384
KEYCERT_SIGN_P521
KEYCERT_SIGN_RSA2048
KEYCERT_SIGN_RSA3072
KEYCERT_SIGN_RSA4096
KEYCERT_SIGN_ED25519
KEYCERT_SIGN_ED25519PH
)
// Key Certificate Public Key Types
const (
KEYCERT_CRYPTO_ELG = iota
KEYCERT_CRYPTO_P256
KEYCERT_CRYPTO_P384
KEYCERT_CRYPTO_P521
KEYCERT_CRYPTO_X25519
)
2022-04-27 10:48:59 -04:00
const (
KEYCERT_MIN_SIZE = 7
)
2024-11-09 00:53:17 -05:00
// signingPublicKey sizes for Signing Key Types
const (
KEYCERT_SIGN_DSA_SHA1_SIZE = 128
KEYCERT_SIGN_P256_SIZE = 64
KEYCERT_SIGN_P384_SIZE = 96
KEYCERT_SIGN_P521_SIZE = 132
KEYCERT_SIGN_RSA2048_SIZE = 256
KEYCERT_SIGN_RSA3072_SIZE = 384
KEYCERT_SIGN_RSA4096_SIZE = 512
KEYCERT_SIGN_ED25519_SIZE = 32
KEYCERT_SIGN_ED25519PH_SIZE = 32
)
2024-11-09 00:53:17 -05:00
// publicKey sizes for Public Key Types
const (
KEYCERT_CRYPTO_ELG_SIZE = 256
KEYCERT_CRYPTO_P256_SIZE = 64
KEYCERT_CRYPTO_P384_SIZE = 96
KEYCERT_CRYPTO_P521_SIZE = 132
KEYCERT_CRYPTO_X25519_SIZE = 32
)
// Sizes of structures in KeyCertificates
const (
KEYCERT_PUBKEY_SIZE = 256
KEYCERT_SPK_SIZE = 128
)
// type KeyCertificate []byte
2022-04-27 10:48:59 -04:00
type KeyCertificate struct {
Certificate
2022-04-27 10:48:59 -04:00
spkType Integer
cpkType Integer
}
2022-09-12 08:31:02 +00:00
// Data returns the raw []byte contained in the Certificate.
func (key_certificate KeyCertificate) Data() ([]byte, error) {
2024-10-18 12:27:42 -04:00
data := key_certificate.Certificate.RawBytes()
log.WithFields(logrus.Fields{
"data_length": len(data),
2024-11-09 00:53:17 -05:00
}).Debug("Retrieved raw data from keyCertificate")
2022-04-27 10:48:59 -04:00
return key_certificate.Certificate.RawBytes(), nil
}
2024-11-09 00:53:17 -05:00
// SigningPublicKeyType returns the signingPublicKey type as a Go integer.
2022-04-27 10:48:59 -04:00
func (key_certificate KeyCertificate) SigningPublicKeyType() (signing_pubkey_type int) {
2024-10-18 12:27:42 -04:00
signing_pubkey_type = key_certificate.spkType.Int()
log.WithFields(logrus.Fields{
"signing_pubkey_type": signing_pubkey_type,
2024-11-09 00:53:17 -05:00
}).Debug("Retrieved signingPublicKey type")
2022-04-27 10:48:59 -04:00
return key_certificate.spkType.Int()
}
2024-11-09 00:53:17 -05:00
// PublicKeyType returns the publicKey type as a Go integer.
2022-04-27 10:48:59 -04:00
func (key_certificate KeyCertificate) PublicKeyType() (pubkey_type int) {
2024-10-18 12:27:42 -04:00
pubkey_type = key_certificate.cpkType.Int()
log.WithFields(logrus.Fields{
"pubkey_type": pubkey_type,
2024-11-09 00:53:17 -05:00
}).Debug("Retrieved publicKey type")
2022-04-27 10:48:59 -04:00
return key_certificate.cpkType.Int()
}
2024-11-09 00:53:17 -05:00
// ConstructPublicKey returns a publicKey constructed using any excess data that may be stored in the KeyCertififcate.
2022-09-12 08:31:02 +00:00
// Returns enr errors encountered while parsing.
func (key_certificate KeyCertificate) ConstructPublicKey(data []byte) (public_key crypto.PublicKey, err error) {
2024-10-18 12:27:42 -04:00
log.WithFields(logrus.Fields{
"input_length": len(data),
2024-11-09 00:53:17 -05:00
}).Debug("Constructing publicKey from keyCertificate")
2022-04-27 10:48:59 -04:00
key_type := key_certificate.PublicKeyType()
if err != nil {
return
}
data_len := len(data)
if data_len < key_certificate.CryptoSize() {
2024-10-18 12:27:42 -04:00
log.WithFields(logrus.Fields{
2024-11-09 00:53:17 -05:00
"at": "(keyCertificate) ConstructPublicKey",
"data_len": data_len,
"required_len": KEYCERT_PUBKEY_SIZE,
"reason": "not enough data",
}).Error("error constructing public key")
2016-02-20 19:02:55 -08:00
err = errors.New("error constructing public key: not enough data")
return
}
switch key_type {
case KEYCERT_CRYPTO_ELG:
var elg_key crypto.ElgPublicKey
copy(elg_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = elg_key
2024-10-18 12:27:42 -04:00
log.Debug("Constructed ElgPublicKey")
case KEYCERT_CRYPTO_X25519:
var ed25519_key crypto.Ed25519PublicKey
copy(ed25519_key[:], data[KEYCERT_PUBKEY_SIZE-KEYCERT_CRYPTO_ELG_SIZE:KEYCERT_PUBKEY_SIZE])
public_key = ed25519_key
2024-10-18 12:27:42 -04:00
log.Debug("Constructed Ed25519PublicKey")
default:
log.WithFields(logrus.Fields{
"key_type": key_type,
}).Warn("Unknown public key type")
}
2024-10-18 12:27:42 -04:00
return
}
2022-09-12 08:31:02 +00:00
// ConstructSigningPublicKey returns a SingingPublicKey constructed using any excess data that may be stored in the KeyCertificate.
// Returns any errors encountered while parsing.
2016-02-20 19:02:55 -08:00
func (key_certificate KeyCertificate) ConstructSigningPublicKey(data []byte) (signing_public_key crypto.SigningPublicKey, err error) {
2024-10-18 12:27:42 -04:00
log.WithFields(logrus.Fields{
"input_length": len(data),
2024-11-09 00:53:17 -05:00
}).Debug("Constructing signingPublicKey from keyCertificate")
signing_key_type := key_certificate.SigningPublicKeyType()
if err != nil {
return
}
data_len := len(data)
if data_len < key_certificate.SignatureSize() {
2024-10-18 12:27:42 -04:00
log.WithFields(logrus.Fields{
2024-11-09 00:53:17 -05:00
"at": "(keyCertificate) ConstructSigningPublicKey",
"data_len": data_len,
"required_len": KEYCERT_SPK_SIZE,
"reason": "not enough data",
}).Error("error constructing signing public key")
2016-02-20 19:02:55 -08:00
err = errors.New("error constructing signing public key: not enough data")
return
}
switch signing_key_type {
case KEYCERT_SIGN_DSA_SHA1:
var dsa_key crypto.DSAPublicKey
copy(dsa_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_DSA_SHA1_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = dsa_key
2024-10-18 12:27:42 -04:00
log.Debug("Constructed DSAPublicKey")
case KEYCERT_SIGN_P256:
2024-11-15 22:29:42 -05:00
var ec_p256_key crypto.ECP256PublicKey
copy(ec_p256_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P256_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p256_key
log.Debug("Constructed P256PublicKey")
case KEYCERT_SIGN_P384:
2024-11-15 22:29:42 -05:00
var ec_p384_key crypto.ECP384PublicKey
copy(ec_p384_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P384_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p384_key
log.Debug("Constructed P384PublicKey")
case KEYCERT_SIGN_P521:
2024-11-15 22:29:42 -05:00
/*var ec_p521_key crypto.ECP521PublicKey
copy(ec_p521_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_P521_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ec_p521_key
log.Debug("Constructed P521PublicKey")*/
panic("unimplemented P521SigningPublicKey")
case KEYCERT_SIGN_RSA2048:
2024-11-15 22:29:42 -05:00
/*var rsa2048_key crypto.RSA2048PublicKey
copy(rsa2048_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_RSA2048_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = rsa2048_key
2024-11-15 22:29:42 -05:00
log.Debug("Constructed RSA2048PublicKey")*/
panic("unimplemented RSA2048SigningPublicKey")
case KEYCERT_SIGN_RSA3072:
2024-11-15 22:29:42 -05:00
/*var rsa3072_key crypto.RSA3072PublicKey
copy(rsa3072_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_RSA3072_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = rsa3072_key
2024-11-15 22:29:42 -05:00
log.Debug("Constructed RSA3072PublicKey")*/
panic("unimplemented RSA3072SigningPublicKey")
case KEYCERT_SIGN_RSA4096:
2024-11-15 22:29:42 -05:00
/*var rsa4096_key crypto.RSA4096PublicKey
copy(rsa4096_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_RSA4096_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = rsa4096_key
2024-11-15 22:29:42 -05:00
log.Debug("Constructed RSA4096PublicKey")*/
panic("unimplemented RSA4096SigningPublicKey")
case KEYCERT_SIGN_ED25519:
var ed25519_key crypto.Ed25519PublicKey
2024-11-15 22:29:42 -05:00
copy(ed25519_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_ED25519_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ed25519_key
2024-11-15 22:29:42 -05:00
log.Debug("Constructed Ed25519PublicKey")
case KEYCERT_SIGN_ED25519PH:
var ed25519ph_key crypto.Ed25519PublicKey
2024-11-15 22:29:42 -05:00
copy(ed25519ph_key[:], data[KEYCERT_SPK_SIZE-KEYCERT_SIGN_ED25519PH_SIZE:KEYCERT_SPK_SIZE])
signing_public_key = ed25519ph_key
2024-11-15 22:29:42 -05:00
log.Debug("Constructed Ed25519PHPublicKey")
2024-10-18 12:27:42 -04:00
default:
log.WithFields(logrus.Fields{
"signing_key_type": signing_key_type,
}).Warn("Unknown signing key type")
panic(err)
}
2024-10-18 12:27:42 -04:00
return
}
2024-11-09 00:53:17 -05:00
// SignatureSize return the size of a Signature corresponding to the Key Certificate's signingPublicKey type.
func (key_certificate KeyCertificate) SignatureSize() (size int) {
sizes := map[int]int{
KEYCERT_SIGN_DSA_SHA1: KEYCERT_SIGN_DSA_SHA1_SIZE,
KEYCERT_SIGN_P256: KEYCERT_SIGN_P256_SIZE,
KEYCERT_SIGN_P384: KEYCERT_SIGN_P384_SIZE,
KEYCERT_SIGN_P521: KEYCERT_SIGN_P521_SIZE,
KEYCERT_SIGN_RSA2048: KEYCERT_SIGN_RSA2048_SIZE,
KEYCERT_SIGN_RSA3072: KEYCERT_SIGN_RSA3072_SIZE,
KEYCERT_SIGN_RSA4096: KEYCERT_SIGN_RSA4096_SIZE,
KEYCERT_SIGN_ED25519: KEYCERT_SIGN_ED25519_SIZE,
KEYCERT_SIGN_ED25519PH: KEYCERT_SIGN_ED25519PH_SIZE,
}
2022-04-27 10:48:59 -04:00
key_type := key_certificate.SigningPublicKeyType()
2024-10-18 12:27:42 -04:00
size = sizes[int(key_type)]
log.WithFields(logrus.Fields{
"key_type": key_type,
"signature_size": size,
}).Debug("Retrieved signature size")
return sizes[int(key_type)]
}
2022-04-27 10:48:59 -04:00
2024-11-09 00:53:17 -05:00
// CryptoSize return the size of a Public Key corresponding to the Key Certificate's publicKey type.
func (key_certificate KeyCertificate) CryptoSize() (size int) {
sizes := map[int]int{
KEYCERT_CRYPTO_ELG: KEYCERT_CRYPTO_ELG_SIZE,
KEYCERT_CRYPTO_P256: KEYCERT_CRYPTO_P256_SIZE,
KEYCERT_CRYPTO_P384: KEYCERT_CRYPTO_P384_SIZE,
KEYCERT_CRYPTO_P521: KEYCERT_CRYPTO_P521_SIZE,
KEYCERT_CRYPTO_X25519: KEYCERT_CRYPTO_X25519_SIZE,
}
key_type := key_certificate.PublicKeyType()
2024-10-18 12:27:42 -04:00
size = sizes[int(key_type)]
log.WithFields(logrus.Fields{
"key_type": key_type,
"crypto_size": size,
}).Debug("Retrieved crypto size")
return sizes[int(key_type)]
}
2022-09-12 08:31:02 +00:00
// NewKeyCertificate creates a new *KeyCertificate from []byte using ReadCertificate.
// The remaining bytes after the specified length are also returned.
// Returns a list of errors that occurred during parsing.
func NewKeyCertificate(bytes []byte) (key_certificate *KeyCertificate, remainder []byte, err error) {
2024-10-18 12:27:42 -04:00
log.WithFields(logrus.Fields{
"input_length": len(bytes),
2024-11-09 00:53:17 -05:00
}).Debug("Creating new keyCertificate")
2024-10-18 12:27:42 -04:00
if len(bytes) < KEYCERT_MIN_SIZE {
log.WithFields(logrus.Fields{
"at": "NewKeyCertificate",
"data_len": len(bytes),
"required_len": KEYCERT_MIN_SIZE,
"reason": "not enough data",
}).Error("error parsing key certificate")
err = errors.New("error parsing key certificate: not enough data")
// Initialize an empty key certificate with zero values
key_certificate = &KeyCertificate{
spkType: Integer{0},
cpkType: Integer{0},
}
return
}
var certificate Certificate
certificate, remainder, err = ReadCertificate(bytes)
if err != nil {
2024-10-18 12:27:42 -04:00
log.WithError(err).Error("Failed to read Certificate")
return
}
key_certificate = &KeyCertificate{
Certificate: certificate,
}
if len(bytes) >= 5 {
key_certificate.spkType = Integer(bytes[4:5])
} else {
key_certificate.spkType = Integer{0}
2022-04-27 10:48:59 -04:00
}
if len(bytes) >= 7 {
key_certificate.cpkType = Integer(bytes[6:7])
} else {
key_certificate.cpkType = Integer{0}
2022-04-27 10:48:59 -04:00
}
2024-10-18 12:27:42 -04:00
log.WithFields(logrus.Fields{
"spk_type": key_certificate.spkType.Int(),
"cpk_type": key_certificate.cpkType.Int(),
"remainder_length": len(remainder),
2024-11-09 00:53:17 -05:00
}).Debug("Successfully created new keyCertificate")
2024-10-18 12:27:42 -04:00
2022-04-27 10:48:59 -04:00
return
}
2022-09-12 08:31:02 +00:00
// KeyCertificateFromCertificate returns a *KeyCertificate from a *Certificate.
func KeyCertificateFromCertificate(certificate Certificate) *KeyCertificate {
2024-11-09 00:53:17 -05:00
log.Debug("Creating keyCertificate from Certificate")
// k, _, _ := NewKeyCertificate(certificate.RawBytes())
2024-10-18 12:27:42 -04:00
k, _, err := NewKeyCertificate(certificate.RawBytes())
if err != nil {
2024-11-09 00:53:17 -05:00
log.WithError(err).Error("Failed to create keyCertificate from Certificate")
2024-10-18 12:27:42 -04:00
} else {
2024-11-09 00:53:17 -05:00
log.Debug("Successfully created keyCertificate from Certificate")
2024-10-18 12:27:42 -04:00
}
2022-04-27 10:48:59 -04:00
return k
}