74 lines
1.7 KiB
Go
74 lines
1.7 KiB
Go
// i2p_secret_key.go
|
|
package i2pkeys
|
|
|
|
import (
|
|
"crypto"
|
|
"crypto/ed25519"
|
|
"crypto/rand"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// SecretKey returns a type-safe secret key implementation
|
|
func (k I2PKeys) SecretKey() (SecretKeyProvider, error) {
|
|
rawKey := k.Private()
|
|
if len(rawKey) != ed25519.PrivateKeySize {
|
|
return nil, fmt.Errorf("%w: expected Ed25519 key", ErrInvalidKeyType)
|
|
}
|
|
|
|
return NewEd25519SecretKey(ed25519.PrivateKey(rawKey))
|
|
}
|
|
|
|
// PrivateKey returns the crypto.PrivateKey interface implementation
|
|
func (k I2PKeys) PrivateKey() (crypto.PrivateKey, error) {
|
|
sk, err := k.SecretKey()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("getting secret key: %w", err)
|
|
}
|
|
return sk, nil
|
|
}
|
|
|
|
// Ed25519PrivateKey safely converts to ed25519.PrivateKey
|
|
func (k I2PKeys) Ed25519PrivateKey() (ed25519.PrivateKey, error) {
|
|
sk, err := k.SecretKey()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if sk.Type() != KeyTypeEd25519 {
|
|
return nil, fmt.Errorf("%w: not an Ed25519 key", ErrInvalidKeyType)
|
|
}
|
|
|
|
return ed25519.PrivateKey(sk.Raw()), nil
|
|
}
|
|
|
|
// Sign implements crypto.Signer
|
|
func (k I2PKeys) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
|
|
sk, err := k.SecretKey()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("getting secret key: %w", err)
|
|
}
|
|
|
|
sig, err := sk.Sign(rand, digest, opts)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%w: %v", ErrSigningFailed, err)
|
|
}
|
|
|
|
return sig, nil
|
|
}
|
|
|
|
// HostnameEntry creates a signed hostname entry
|
|
func (k I2PKeys) HostnameEntry(hostname string, opts crypto.SignerOpts) (string, error) {
|
|
if hostname == "" {
|
|
return "", errors.New("empty hostname")
|
|
}
|
|
|
|
sig, err := k.Sign(rand.Reader, []byte(hostname), opts)
|
|
if err != nil {
|
|
return "", fmt.Errorf("signing hostname: %w", err)
|
|
}
|
|
|
|
return string(sig), nil
|
|
}
|