package keys import ( "crypto/rand" "crypto/rsa" "crypto/sha512" "crypto/subtle" "crypto/x509" "errors" "io" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/strkey" "github.com/libp2p/go-libp2p-core/crypto" crypto_pb "github.com/libp2p/go-libp2p-core/crypto/pb" ) type SigningPubKey crypto.PubKey type SigningPrivKey crypto.PrivKey var MinRsaKeyBits = 2048 var ErrKeyLengthTooSmall = errors.New("error key length too small") type Key interface { Equals(Key) bool Raw() ([]byte, error) } type EncryptionPrivKey interface { Key Decrypt([]byte) ([]byte, error) GetPublic() EncryptionPubKey } type EncryptionPubKey interface { Key Encrypt(data []byte) ([]byte, error) } type EncryptionRsaPrivKey struct { privKey rsa.PrivateKey } type EncryptionRsaPubKey struct { pubKey rsa.PublicKey } func (e *EncryptionRsaPubKey) Equals(key Key) bool { other, ok := (key).(*EncryptionRsaPubKey) if !ok { return keyEquals(e, key) } return e.pubKey.N.Cmp(other.pubKey.N) == 0 && e.pubKey.E == other.pubKey.E } func (e *EncryptionRsaPubKey) Raw() ([]byte, error) { return x509.MarshalPKIXPublicKey(&e.pubKey) } func (e *EncryptionRsaPubKey) Encrypt(data []byte) ([]byte, error) { hash := sha512.New() return rsa.EncryptOAEP(hash, rand.Reader, &e.pubKey, data, nil) } func (e *EncryptionRsaPrivKey) Equals(key Key) bool { other, ok := (key).(*EncryptionRsaPrivKey) if !ok { return keyEquals(e, key) } return e.privKey.N.Cmp(other.privKey.N) == 0 && e.privKey.E == other.privKey.E } func (e *EncryptionRsaPrivKey) Raw() ([]byte, error) { b := x509.MarshalPKCS1PrivateKey(&e.privKey) return b, nil } func (e *EncryptionRsaPrivKey) Decrypt(bytes []byte) ([]byte, error) { hash := sha512.New() return rsa.DecryptOAEP(hash, rand.Reader, &e.privKey, bytes, nil) } func (e *EncryptionRsaPrivKey) GetPublic() EncryptionPubKey { return &EncryptionRsaPubKey{pubKey: e.privKey.PublicKey} } func GenerateRandomRSAKeyPair(bits int) (EncryptionPrivKey, EncryptionPubKey, error) { return GenerateRSAKeyPair(bits, rand.Reader) } func GenerateRSAKeyPair(bits int, src io.Reader) (EncryptionPrivKey, EncryptionPubKey, error) { if bits < MinRsaKeyBits { return nil, nil, ErrKeyLengthTooSmall } priv, err := rsa.GenerateKey(src, bits) if err != nil { return nil, nil, err } pk := priv.PublicKey return &EncryptionRsaPrivKey{privKey: *priv}, &EncryptionRsaPubKey{pubKey: pk}, nil } func NewEncryptionRsaPrivKeyFromBytes(bytes []byte) (EncryptionPrivKey, error) { sk, err := x509.ParsePKCS1PrivateKey(bytes) if err != nil { return nil, err } if sk.N.BitLen() < MinRsaKeyBits { return nil, ErrKeyLengthTooSmall } return &EncryptionRsaPrivKey{privKey: *sk}, nil } func NewEncryptionRsaPubKeyFromBytes(bytes []byte) (EncryptionPubKey, error) { pub, err := x509.ParsePKIXPublicKey(bytes) if err != nil { return nil, err } pk, ok := pub.(*rsa.PublicKey) if !ok { return nil, errors.New("not actually an rsa public key") } if pk.N.BitLen() < MinRsaKeyBits { return nil, ErrKeyLengthTooSmall } return &EncryptionRsaPubKey{pubKey: *pk}, nil } func NewSigningEd25519PubKeyFromBytes(bytes []byte) (SigningPubKey, error) { return crypto.UnmarshalEd25519PublicKey(bytes) } func GenerateRandomEd25519KeyPair() (SigningPrivKey, SigningPubKey, error) { return crypto.GenerateEd25519Key(rand.Reader) } func keyEquals(k1, k2 Key) bool { a, err := k1.Raw() if err != nil { return false } b, err := k2.Raw() if err != nil { return false } return subtle.ConstantTimeCompare(a, b) == 1 } type Ed25519SigningPubKeyDecoder struct{} func NewEd25519Decoder() *Ed25519SigningPubKeyDecoder { return &Ed25519SigningPubKeyDecoder{} } func (e *Ed25519SigningPubKeyDecoder) DecodeFromBytes(bytes []byte) (SigningPubKey, error) { return NewSigningEd25519PubKeyFromBytes(bytes) } func (e *Ed25519SigningPubKeyDecoder) DecodeFromString(identity string) (SigningPubKey, error) { pubKeyRaw, err := strkey.Decode(0x5b, identity) if err != nil { return nil, err } return e.DecodeFromBytes(pubKeyRaw) } func (e *Ed25519SigningPubKeyDecoder) DecodeFromStringIntoBytes(identity string) ([]byte, error) { return strkey.Decode(0x5b, identity) } func (e *Ed25519SigningPubKeyDecoder) EncodeToString(pubkey crypto.PubKey) (string, error) { raw, err := pubkey.Raw() if err != nil { return "", err } return strkey.Encode(0x5b, raw) } type SigningPubKeyDecoder interface { DecodeFromBytes(bytes []byte) (SigningPubKey, error) DecodeFromString(identity string) (SigningPubKey, error) DecodeFromStringIntoBytes(identity string) ([]byte, error) } // Below keys are required for testing and mocking purposes type EmptyRecorderEncryptionKey struct { recordedEncrypted [][]byte recordedDecrypted [][]byte } func (f *EmptyRecorderEncryptionKey) Equals(key Key) bool { return true } func (f *EmptyRecorderEncryptionKey) Raw() ([]byte, error) { panic("can't get bytes from this key") } func (f *EmptyRecorderEncryptionKey) GetPublic() EncryptionPubKey { panic("this key doesn't have a public key") } func (f *EmptyRecorderEncryptionKey) Encrypt(msg []byte) ([]byte, error) { f.recordedEncrypted = append(f.recordedEncrypted, msg) return msg, nil } func (f *EmptyRecorderEncryptionKey) Decrypt(msg []byte) ([]byte, error) { f.recordedDecrypted = append(f.recordedDecrypted, msg) return msg, nil } type SignatureVerificationPayload struct { message []byte signature []byte } type EmptyRecorderVerificationKey struct { verifications []SignatureVerificationPayload } func (e *EmptyRecorderVerificationKey) Bytes() ([]byte, error) { panic("can't get bytes from this key") } func (e *EmptyRecorderVerificationKey) Equals(key crypto.Key) bool { return true } func (e *EmptyRecorderVerificationKey) Raw() ([]byte, error) { panic("can't get bytes from this key") } func (e *EmptyRecorderVerificationKey) Type() crypto_pb.KeyType { panic("can't get type from this key") } func (e *EmptyRecorderVerificationKey) Verify(data []byte, sig []byte) (bool, error) { e.verifications = append(e.verifications, SignatureVerificationPayload{ message: data, signature: sig, }) return true, nil } func NewMockSigningPubKeyFromBytes(bytes []byte) (SigningPubKey, error) { return &EmptyRecorderVerificationKey{}, nil }