2016-01-29 07:35:17 -05:00
|
|
|
package common
|
2016-01-28 12:58:58 -05:00
|
|
|
|
2016-02-14 22:28:20 -08:00
|
|
|
/*
|
|
|
|
I2P Certificate
|
2016-06-16 23:17:21 -07:00
|
|
|
https://geti2p.net/spec/common-structures#certificate
|
2016-02-14 22:28:20 -08:00
|
|
|
Accurate for version 0.9.24
|
|
|
|
|
|
|
|
+----+----+----+----+----+-//
|
|
|
|
|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-01-28 12:58:58 -05:00
|
|
|
import (
|
2016-02-05 02:23:11 -08:00
|
|
|
"errors"
|
2021-10-22 17:17:55 -04:00
|
|
|
|
2021-04-19 20:43:37 -04:00
|
|
|
log "github.com/sirupsen/logrus"
|
2016-01-28 12:58:58 -05:00
|
|
|
)
|
|
|
|
|
2016-02-13 21:00:29 -08:00
|
|
|
// Certificate Types
|
2016-01-28 12:58:58 -05:00
|
|
|
const (
|
2016-01-29 07:22:31 -05:00
|
|
|
CERT_NULL = iota
|
|
|
|
CERT_HASHCASH
|
|
|
|
CERT_HIDDEN
|
|
|
|
CERT_SIGNED
|
|
|
|
CERT_MULTIPLE
|
|
|
|
CERT_KEY
|
2016-01-28 12:58:58 -05:00
|
|
|
)
|
|
|
|
|
2016-06-17 21:07:16 -07:00
|
|
|
// Minimum size of a valid Certificate
|
2016-02-14 22:28:20 -08:00
|
|
|
const (
|
2016-02-16 01:04:40 -08:00
|
|
|
CERT_MIN_SIZE = 3
|
2016-02-14 22:28:20 -08:00
|
|
|
)
|
|
|
|
|
2021-04-22 22:55:32 -04:00
|
|
|
type CertificateInterface interface {
|
|
|
|
Cert() []byte
|
|
|
|
Length() (length int, err error)
|
|
|
|
Data() (data []byte, err error)
|
2021-06-29 19:34:41 -04:00
|
|
|
Type() (cert_type int, type_bytes []byte, err error)
|
2021-04-24 19:20:37 -04:00
|
|
|
SignatureSize() (size int)
|
2021-04-22 22:55:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
type Certificate struct {
|
2021-07-27 11:42:46 -04:00
|
|
|
CertType *Integer
|
|
|
|
CertLen *Integer
|
2021-04-22 22:55:32 -04:00
|
|
|
CertBytes []byte
|
|
|
|
}
|
|
|
|
|
|
|
|
var ci CertificateInterface = &Certificate{}
|
|
|
|
|
2021-04-24 19:20:37 -04:00
|
|
|
func (certificate Certificate) SignatureSize() (size int) {
|
|
|
|
return 40
|
|
|
|
}
|
|
|
|
|
2021-04-22 22:55:32 -04:00
|
|
|
func (certificate Certificate) Cert() []byte {
|
2021-04-24 15:32:45 -04:00
|
|
|
var ret []byte
|
2021-06-29 19:34:41 -04:00
|
|
|
ret = append(ret, certificate.CertType.Bytes()...)
|
2021-10-25 21:02:45 -04:00
|
|
|
l, _ := certificate.Length()
|
|
|
|
//if err != nil && err.Error() != "certificate parsing warning: certificate data is shorter than specified by length" {
|
|
|
|
//}
|
2021-04-25 02:23:54 -04:00
|
|
|
data, _ := certificate.Data()
|
2021-10-25 21:02:45 -04:00
|
|
|
if l != 0 && len(data) != 0 {
|
2021-07-27 11:42:46 -04:00
|
|
|
ret = append(ret, certificate.CertLen.Bytes()...)
|
2021-04-25 02:23:54 -04:00
|
|
|
ret = append(ret, data...)
|
|
|
|
} else {
|
2021-06-29 19:34:41 -04:00
|
|
|
ret = append(ret, certificate.CertLen.Bytes()...)
|
2021-04-25 02:23:54 -04:00
|
|
|
}
|
2021-10-25 21:02:45 -04:00
|
|
|
//log.Println("\n\n CERTIFICATE: ", ret, l+CERT_MIN_SIZE, err)
|
|
|
|
return ret //[:l+CERT_MIN_SIZE]
|
2021-04-22 22:55:32 -04:00
|
|
|
}
|
2016-01-28 12:58:58 -05:00
|
|
|
|
2016-02-14 22:28:20 -08:00
|
|
|
//
|
|
|
|
// Return the Certificate Type specified in the first byte of the Certificate,
|
|
|
|
// and an error if the certificate is shorter than the minimum certificate size.
|
|
|
|
//
|
2021-06-29 19:34:41 -04:00
|
|
|
func (certificate Certificate) Type() (cert_type int, type_bytes []byte, err error) {
|
|
|
|
return certificate.CertType.Value(), certificate.CertType.Bytes(), nil
|
2016-01-28 12:58:58 -05:00
|
|
|
}
|
|
|
|
|
2016-02-06 01:42:47 -08:00
|
|
|
//
|
2016-02-14 22:28:20 -08:00
|
|
|
// Look up the length of the Certificate, reporting errors if the certificate is
|
|
|
|
// shorter than the minimum certificate size or if the reported length doesn't
|
|
|
|
// match the provided data.
|
2016-02-06 01:42:47 -08:00
|
|
|
//
|
2016-02-14 22:28:20 -08:00
|
|
|
func (certificate Certificate) Length() (length int, err error) {
|
2021-06-29 19:34:41 -04:00
|
|
|
if certificate.CertLen.Value() < 1 {
|
2021-04-24 22:48:48 -04:00
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"at": "(Certificate) Length",
|
2021-04-25 02:06:57 -04:00
|
|
|
"certificate_bytes_length": certificate.CertLen,
|
|
|
|
"certificate_min_size": CERT_MIN_SIZE - 1,
|
|
|
|
"reason": "certificate is too short",
|
2021-04-24 22:48:48 -04:00
|
|
|
}).Warn("certificate format warning")
|
2021-04-24 23:23:29 -04:00
|
|
|
err = errors.New("error parsing certificate length: certificate is too short")
|
2021-04-25 02:06:57 -04:00
|
|
|
}
|
2021-06-29 19:34:41 -04:00
|
|
|
if certificate.CertLen.Value() > len(certificate.CertBytes) {
|
2021-04-25 02:06:57 -04:00
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"at": "(Certificate) Length",
|
|
|
|
"certificate_bytes_length": certificate.CertLen,
|
|
|
|
"certificate_actual_length": len(certificate.CertBytes),
|
|
|
|
"reason": "certificate data is shorter than specified by length",
|
|
|
|
}).Warn("certificate format warning")
|
|
|
|
err = errors.New("certificate parsing warning: certificate data is shorter than specified by length")
|
2021-10-25 21:02:45 -04:00
|
|
|
length = certificate.CertLen.Value()
|
2021-04-25 02:06:57 -04:00
|
|
|
}
|
2021-06-29 19:34:41 -04:00
|
|
|
if certificate.CertLen.Value() < len(certificate.CertBytes) {
|
2021-04-25 02:06:57 -04:00
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"at": "(Certificate) Length",
|
|
|
|
"certificate_bytes_length": certificate.CertLen,
|
|
|
|
"certificate_actual_length": len(certificate.CertBytes),
|
|
|
|
"reason": "certificate contains data beyond length",
|
|
|
|
}).Warn("certificate format warning")
|
2021-10-25 21:02:45 -04:00
|
|
|
err = errors.New("certificate parsing warning: certificate data is longer than specified by length")
|
2021-06-29 19:34:41 -04:00
|
|
|
length = certificate.CertLen.Value()
|
2021-04-24 22:48:48 -04:00
|
|
|
}
|
2016-02-14 22:28:20 -08:00
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
2021-10-25 21:02:45 -04:00
|
|
|
length = certificate.CertLen.Value()
|
2016-02-14 22:28:20 -08:00
|
|
|
return
|
2016-01-28 12:58:58 -05:00
|
|
|
}
|
|
|
|
|
2016-02-06 01:42:47 -08:00
|
|
|
//
|
2016-02-14 22:28:20 -08:00
|
|
|
// Return the Certificate data and any errors encountered parsing the Certificate.
|
2016-02-06 01:42:47 -08:00
|
|
|
//
|
2016-02-14 22:28:20 -08:00
|
|
|
func (certificate Certificate) Data() (data []byte, err error) {
|
2021-04-25 02:06:57 -04:00
|
|
|
_, err = certificate.Length()
|
2021-06-29 19:34:41 -04:00
|
|
|
data = certificate.CertBytes
|
2016-02-05 02:23:11 -08:00
|
|
|
if err != nil {
|
|
|
|
switch err.Error() {
|
|
|
|
case "error parsing certificate length: certificate is too short":
|
2016-02-14 22:28:20 -08:00
|
|
|
return
|
2016-02-05 02:23:11 -08:00
|
|
|
case "certificate parsing warning: certificate data is shorter than specified by length":
|
2021-04-25 02:06:57 -04:00
|
|
|
data = certificate.CertBytes
|
2016-02-14 22:28:20 -08:00
|
|
|
return
|
2021-10-25 21:02:45 -04:00
|
|
|
case "certificate parsing warning: certificate data is longer than specified by length":
|
2021-06-29 19:34:41 -04:00
|
|
|
data = certificate.CertBytes[:certificate.CertLen.Value()]
|
2016-02-14 22:28:20 -08:00
|
|
|
return
|
2016-02-05 02:23:11 -08:00
|
|
|
}
|
2016-01-29 07:22:31 -05:00
|
|
|
}
|
2016-02-14 22:28:20 -08:00
|
|
|
return
|
2016-01-28 12:58:58 -05:00
|
|
|
}
|
2016-02-01 01:56:10 -08:00
|
|
|
|
2016-02-06 01:42:47 -08:00
|
|
|
//
|
2016-02-14 22:28:20 -08:00
|
|
|
// Read a Certificate from a slice of bytes, returning any extra data on the end of the slice
|
|
|
|
// and any errors if a valid Certificate could not be read.
|
2016-02-06 01:42:47 -08:00
|
|
|
//
|
2021-07-28 08:09:30 -04:00
|
|
|
func ReadCertificate(data []byte) (certificate *Certificate, remainder []byte, err error) {
|
|
|
|
certificate = &Certificate{}
|
2021-06-29 19:34:41 -04:00
|
|
|
certificate.CertType, err = NewInteger(data[0:1])
|
2021-10-25 21:02:45 -04:00
|
|
|
if err != nil {
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"at": "(Certificate) ReadCertificate",
|
|
|
|
"certificate": certificate,
|
|
|
|
"data": data,
|
|
|
|
"reason": "error parsing certificate type",
|
|
|
|
"error": err,
|
|
|
|
"error_reason": err.Error(),
|
|
|
|
}).Warn("certificate format warning")
|
|
|
|
}
|
2021-07-27 12:46:11 -04:00
|
|
|
certificate.CertLen = &Integer{}
|
2021-04-22 22:55:32 -04:00
|
|
|
cert_len := len(data)
|
2021-04-24 23:23:29 -04:00
|
|
|
|
2021-04-24 22:48:48 -04:00
|
|
|
if cert_len < CERT_MIN_SIZE {
|
2021-04-22 22:55:32 -04:00
|
|
|
log.WithFields(log.Fields{
|
2021-04-25 02:06:57 -04:00
|
|
|
"at": "(Certificate) ReadCertificate",
|
2021-04-22 22:55:32 -04:00
|
|
|
"certificate_bytes_length": cert_len,
|
2021-04-25 02:06:57 -04:00
|
|
|
"certificate_min_size": CERT_MIN_SIZE,
|
|
|
|
"reason": "certificate is too short",
|
2021-04-22 22:55:32 -04:00
|
|
|
}).Warn("certificate format warning")
|
2021-04-25 02:06:57 -04:00
|
|
|
err = errors.New("error parsing certificate length: certificate is too short")
|
2021-04-24 22:48:48 -04:00
|
|
|
return
|
|
|
|
} else {
|
2021-07-27 12:55:03 -04:00
|
|
|
certificate.CertLen, err = NewInteger(data[1:CERT_MIN_SIZE])
|
2021-06-29 19:34:41 -04:00
|
|
|
// _, err = certificate.Type()
|
2021-10-25 21:02:45 -04:00
|
|
|
//log.Println("Calculated len AT LEN", cert_len, "Stated len AT LEN", certificate.CertLen.Value())
|
2021-10-22 17:17:55 -04:00
|
|
|
if err != nil {
|
|
|
|
//return
|
|
|
|
log.WithFields(log.Fields{
|
|
|
|
"at": "(Certificate) ReadCertificate",
|
|
|
|
"certificate_bytes_length": cert_len,
|
|
|
|
"certificate_min_size": CERT_MIN_SIZE,
|
|
|
|
"reason": "certificate size is invalid",
|
|
|
|
}).Warn("certificate format warning")
|
2021-10-25 21:02:45 -04:00
|
|
|
//err = errors.New("error parsing certificate type: certificate type is invalid")
|
2021-10-22 17:17:55 -04:00
|
|
|
}
|
2021-04-24 22:48:48 -04:00
|
|
|
certificate.CertBytes = data[CERT_MIN_SIZE:]
|
2021-04-24 23:23:29 -04:00
|
|
|
_, err = certificate.Length()
|
2021-04-25 02:06:57 -04:00
|
|
|
if err != nil {
|
|
|
|
switch err.Error() {
|
|
|
|
case "error parsing certificate length: certificate is too short":
|
2021-06-29 19:34:41 -04:00
|
|
|
certificate.CertLen, err = NewInteger([]byte{00000000})
|
2021-04-25 02:06:57 -04:00
|
|
|
return
|
|
|
|
case "certificate parsing warning: certificate data is shorter than specified by length":
|
|
|
|
return
|
2021-10-25 21:02:45 -04:00
|
|
|
case "certificate parsing warning: certificate data is longer than specified by length":
|
2021-04-25 02:06:57 -04:00
|
|
|
certificate.CertBytes = data[CERT_MIN_SIZE:]
|
2021-10-25 21:02:45 -04:00
|
|
|
l, _ := certificate.Length()
|
|
|
|
remainder = data[CERT_MIN_SIZE+l:]
|
2021-04-25 02:06:57 -04:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2016-02-05 02:23:11 -08:00
|
|
|
}
|
2021-04-25 02:06:57 -04:00
|
|
|
|
2021-04-24 22:48:48 -04:00
|
|
|
return
|
2016-02-01 01:56:10 -08:00
|
|
|
}
|