diff --git a/internal/service/signer/service.go b/internal/service/signer/service.go
index bd9789da950bb53d8710651a57ebe0af3895ce51..685ecd112e4d870f4f58e8601753780d316307c4 100644
--- a/internal/service/signer/service.go
+++ b/internal/service/signer/service.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"crypto/ed25519"
 	"crypto/x509"
+	"encoding/base64"
 	"encoding/json"
 	"encoding/pem"
 	"fmt"
@@ -523,6 +524,31 @@ func (s *Service) VerifyPresentation(_ context.Context, req *signer.VerifyPresen
 	return &signer.VerifyResult{Valid: true}, nil
 }
 
+// Sign creates digital signature on base64 encoded binary data.
+func (s *Service) Sign(_ context.Context, req *signer.SignRequest) (res *signer.SignResult, err error) {
+	logger := s.logger.With(
+		zap.String("operation", "sign"),
+		zap.String("namespace", req.Namespace),
+		zap.String("key", req.Key),
+	)
+
+	data, err := base64.StdEncoding.DecodeString(req.Data)
+	if err != nil {
+		logger.Error("cannot base64 decode data", zap.Error(err))
+		return nil, errors.New(errors.BadRequest, "cannot base64 decode data", err)
+	}
+
+	signature, err := s.vault.WithKey(req.Namespace, req.Key).Sign(data)
+	if err != nil {
+		logger.Error("error signing data", zap.Error(err))
+		return nil, errors.New(err)
+	}
+
+	encodedSignature := base64.StdEncoding.EncodeToString(signature)
+
+	return &signer.SignResult{Signature: encodedSignature}, nil
+}
+
 func (s *Service) supportedKey(keyType string) bool {
 	for _, kt := range s.supportedKeys {
 		if kt == keyType {
diff --git a/internal/service/signer/service_test.go b/internal/service/signer/service_test.go
index 6bcbd42f2da3108ae9a2178049c43430ecdb16a6..70c919ad404ace0ed2545cf1811e80539e1aae7a 100644
--- a/internal/service/signer/service_test.go
+++ b/internal/service/signer/service_test.go
@@ -818,6 +818,75 @@ func TestService_CreateCredential(t *testing.T) {
 	}
 }
 
+func TestService_Sign(t *testing.T) {
+	tests := []struct {
+		name string
+		// input
+		signer signer.Vault
+		data   string
+		// output
+		signature string
+		errkind   errors.Kind
+		errtext   string
+	}{
+		{
+			name:    "invalid encoding of data",
+			data:    "not base64 encoded string",
+			errtext: "cannot base64 decode data",
+			errkind: errors.BadRequest,
+		},
+		{
+			name: "signing key not found",
+			data: base64.StdEncoding.EncodeToString([]byte("something")),
+			signer: &signerfakes.FakeVault{
+				WithKeyStub: func(namespace string, key string) signer.Vault {
+					return &signerfakes.FakeVault{SignStub: func(data []byte) ([]byte, error) {
+						return nil, errors.New(errors.NotFound, "key not found")
+					}}
+				},
+			},
+			errtext: "key not found",
+			errkind: errors.NotFound,
+		},
+		{
+			name: "successful signing",
+			data: base64.StdEncoding.EncodeToString([]byte("something")),
+			signer: &signerfakes.FakeVault{
+				WithKeyStub: func(namespace string, key string) signer.Vault {
+					return &signerfakes.FakeVault{SignStub: func(data []byte) ([]byte, error) {
+						return []byte("signature"), nil
+					}}
+				},
+			},
+			signature: base64.StdEncoding.EncodeToString([]byte("signature")),
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			svc := signer.New(test.signer, nil, nil, zap.NewNop())
+			result, err := svc.Sign(context.Background(), &goasigner.SignRequest{
+				Namespace: "transit",
+				Key:       "key1",
+				Data:      test.data,
+			})
+			if err != nil {
+				require.NotEmpty(t, test.errtext, "expected no error but got %s", err)
+				require.Nil(t, result)
+				assert.ErrorContains(t, err, test.errtext)
+				e, ok := err.(*errors.Error)
+				require.True(t, ok)
+				assert.Equal(t, test.errkind, e.Kind)
+				return
+			}
+
+			require.Empty(t, test.errtext, "got no error, but expected: %s", test.errtext)
+			require.NotNil(t, result)
+			assert.Equal(t, test.signature, result.Signature)
+		})
+	}
+}
+
 // ---------- Verifiable Credentials ---------- //
 
 //nolint:gosec