diff --git a/src/common/errcode.c b/src/common/errcode.c
index 9671ee581c86e04d53300508b5b008f255218fbd..10b6546e828d0aeb81ab171f01a7d1e6ab29e358 100644
--- a/src/common/errcode.c
+++ b/src/common/errcode.c
@@ -97,13 +97,14 @@ const error_table_t knot_error_msgs[] = {
 	{ KNOT_KEY_EPRIVATE_KEY_OPEN, "Cannot open private key file." },
 	{ KNOT_KEY_EPUBLIC_KEY_INVALID, "Public key file is invalid." },
 
-	/* Key signing errors. */
+	/* Key signing/verification errors. */
 	{ KNOT_DNSSEC_ENOTSUP, "Signing algorithm is not supported." },
 	{ KNOT_DNSSEC_EINVALID_KEY, "The signing key is invalid." },
 	{ KNOT_DNSSEC_EASSIGN_KEY, "Cannot assign the key." },
 	{ KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT, "Cannot create digest context." },
 	{ KNOT_DNSSEC_EUNEXPECTED_SIGNATURE_SIZE, "Unexpected signature size." },
 	{ KNOT_DNSSEC_EDECODE_RAW_SIGNATURE, "Cannot decode the raw signature." },
+	{ KNOT_DNSSEC_EINVALID_SIGNATURE, "Signature is invalid." },
 	{ KNOT_DNSSEC_ESIGN, "Cannot create the signature." },
 
 	/* NSEC3 errors. */
diff --git a/src/common/errcode.h b/src/common/errcode.h
index 92f68d5374b74cce0debbec0f1a5c85545c95ca7..038cb16d6965c36b6912db8a989d2cf89401b686 100644
--- a/src/common/errcode.h
+++ b/src/common/errcode.h
@@ -123,6 +123,7 @@ enum knot_error {
 	KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT,
 	KNOT_DNSSEC_EUNEXPECTED_SIGNATURE_SIZE,
 	KNOT_DNSSEC_EDECODE_RAW_SIGNATURE,
+	KNOT_DNSSEC_EINVALID_SIGNATURE,
 	KNOT_DNSSEC_ESIGN,
 
 	/* NSEC3 errors. */
diff --git a/src/libknot/dnssec/sign.c b/src/libknot/dnssec/sign.c
index a165f66a857f10c165bbc253e667eafe21c9b236..f91737f7726bbf2ad0c89e03f33ea0c689fbe93a 100644
--- a/src/libknot/dnssec/sign.c
+++ b/src/libknot/dnssec/sign.c
@@ -56,6 +56,8 @@ struct algorithm_functions {
 	int (*sign_add)(const knot_dnssec_sign_context_t *, const uint8_t *, size_t);
 	//! \brief Callback: finish the signing and write out the signature.
 	int (*sign_write)(const knot_dnssec_sign_context_t *, uint8_t *);
+	//! \brief Callback: finish the signing and validate the signature.
+	int (*sign_verify)(const knot_dnssec_sign_context_t *, const uint8_t *, size_t);
 };
 
 /**
@@ -97,7 +99,7 @@ static int any_sign_add(const knot_dnssec_sign_context_t *context,
 	assert(context);
 	assert(data);
 
-	if (!EVP_SignUpdate(context->digest_context, data, data_size))
+	if (!EVP_DigestUpdate(context->digest_context, data, data_size))
 		return KNOT_DNSSEC_ESIGN;
 
 	return KNOT_EOK;
@@ -114,7 +116,7 @@ static int any_sign_add(const knot_dnssec_sign_context_t *context,
  *
  * \return Error code, KNOT_EOK if successful.
  */
-static int any_sign_finish(const knot_dnssec_sign_context_t *context,
+static int any_sign_write(const knot_dnssec_sign_context_t *context,
                            uint8_t **signature, size_t *signature_size)
 {
 	assert(context);
@@ -142,6 +144,30 @@ static int any_sign_finish(const knot_dnssec_sign_context_t *context,
 	return KNOT_EOK;
 }
 
+/*!
+ * \brief Verify the DNSSEC signature for supplied data.
+ *
+ * \param context         DNSSEC signature context.
+ * \param signature       Pointer to signature.
+ * \param signature_size  Size of the signature.
+ *
+ * \return Error code.
+ * \retval KNOT_EOK                        The signature is valid.
+ * \retval KNOT_DNSSEC_EINVALID_SIGNATURE  The signature is invalid.
+ */
+static int any_sign_verify(const knot_dnssec_sign_context_t *context,
+                            const uint8_t *signature, size_t signature_size)
+{
+	assert(context);
+	assert(signature);
+
+	int result = EVP_VerifyFinal(context->digest_context,
+	                             signature, signature_size,
+	                             context->key->data->private_key);
+
+	return result == 1 ? KNOT_EOK : KNOT_DNSSEC_EINVALID_SIGNATURE;
+}
+
 /*- RSA specific -------------------------------------------------------------*/
 
 /*!
@@ -201,7 +227,7 @@ static int rsa_sign_write(const knot_dnssec_sign_context_t *context,
 	size_t raw_signature_size;
 	const knot_dnssec_key_t *key = context->key;
 
-	result = any_sign_finish(context, &raw_signature, &raw_signature_size);
+	result = any_sign_write(context, &raw_signature, &raw_signature_size);
 	if (result != KNOT_EOK) {
 		return result;
 	}
@@ -270,7 +296,7 @@ static int dsa_sign_write(const knot_dnssec_sign_context_t *context,
 	uint8_t *raw_signature;
 	size_t raw_signature_size;
 
-	result = any_sign_finish(context, &raw_signature, &raw_signature_size);
+	result = any_sign_write(context, &raw_signature, &raw_signature_size);
 	if (result != KNOT_EOK) {
 		return result;
 	}
@@ -380,7 +406,7 @@ static int ecdsa_sign_write(const knot_dnssec_sign_context_t *context,
 	uint8_t *raw_signature;
 	size_t raw_signature_size;
 
-	result = any_sign_finish(context, &raw_signature, &raw_signature_size);
+	result = any_sign_write(context, &raw_signature, &raw_signature_size);
 	if (result != KNOT_EOK) {
 		return result;
 	}
@@ -428,14 +454,16 @@ static const algorithm_functions_t rsa_functions = {
 	rsa_create_pkey,
 	any_sign_size,
 	any_sign_add,
-	rsa_sign_write
+	rsa_sign_write,
+	any_sign_verify
 };
 
 static const algorithm_functions_t dsa_functions = {
 	dsa_create_pkey,
 	dsa_sign_size,
 	any_sign_add,
-	dsa_sign_write
+	dsa_sign_write,
+	any_sign_verify
 };
 
 #ifndef OPENSSL_NO_ECDSA
@@ -443,7 +471,8 @@ static const algorithm_functions_t ecdsa_functions = {
 	ecdsa_create_pkey,
 	ecdsa_sign_size,
 	any_sign_add,
-	ecdsa_sign_write
+	ecdsa_sign_write,
+	any_sign_verify
 };
 #endif
 
@@ -559,7 +588,7 @@ static int create_digest_context(const knot_dnssec_key_t *key,
 	if (!context)
 		return KNOT_ENOMEM;
 
-	if (!EVP_SignInit_ex(context, digest_type, NULL)) {
+	if (!EVP_DigestInit_ex(context, digest_type, NULL)) {
 		EVP_MD_CTX_destroy(context);
 		return KNOT_DNSSEC_ECREATE_DIGEST_CONTEXT;
 	}
@@ -738,19 +767,20 @@ size_t knot_dnssec_sign_size(const knot_dnssec_key_t *key)
 	return key->data->functions->sign_size(key);
 }
 
-/*!
- * \brief Get DNSSEC key used by given signing context.
+/**
+ * \brief Clean DNSSEC signing context to start a new signature.
  */
-const knot_dnssec_key_t *knot_dnssec_sign_key(knot_dnssec_sign_context_t *context)
+int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context)
 {
 	if (!context)
-		return NULL;
+		return KNOT_EINVAL;
 
-	return context->key;
+	destroy_digest_context(&context->digest_context);
+	return create_digest_context(context->key, &context->digest_context);
 }
 
 /*!
- * \brief Add data into DNSSEC signature.
+ * \brief Add data to be covered by DNSSEC signature.
  */
 int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context,
                          const uint8_t *data, size_t data_size)
@@ -762,7 +792,7 @@ int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context,
 }
 
 /**
- * \brief Finish DNSSEC signing and write out the signature.
+ * \brief Write down the DNSSEC signature for supplied data.
  */
 int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context, uint8_t *signature)
 {
@@ -773,13 +803,14 @@ int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context, uint8_t *signatu
 }
 
 /**
- * \brief Clean DNSSEC signing context to start a new signature.
+ * \brief Verify the DNSSEC signature for supplied data.
  */
-int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context)
+int knot_dnssec_sign_verify(knot_dnssec_sign_context_t *context,
+			    const uint8_t *signature, size_t signature_size)
 {
-	if (!context)
+	if (!context || !context->key || !signature)
 		return KNOT_EINVAL;
 
-	destroy_digest_context(&context->digest_context);
-	return create_digest_context(context->key, &context->digest_context);
+	return context->key->data->functions->sign_verify(context, signature,
+	                                                  signature_size);
 }
diff --git a/src/libknot/dnssec/sign.h b/src/libknot/dnssec/sign.h
index b302f85f6850ab59b7166c2e8158e1dfe16a8de0..2e4950921fa82117ec4a7e69395206ff0cd6685a 100644
--- a/src/libknot/dnssec/sign.h
+++ b/src/libknot/dnssec/sign.h
@@ -103,8 +103,19 @@ void knot_dnssec_sign_free(knot_dnssec_sign_context_t *context);
  */
 size_t knot_dnssec_sign_size(const knot_dnssec_key_t *key);
 
+/**
+ * \brief Clean DNSSEC signing context to start a new signature.
+ *
+ * Need not be called after knot_dnssec_sign_init().
+ *
+ * \param context	DNSSEC signing context.
+ *
+ * \return Error code, KNOT_EOK if successful.
+ */
+int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context);
+
 /*!
- * \brief Add data into DNSSEC signature.
+ * \brief Add data to be covered by DNSSEC signature.
  *
  * \param context    DNSSEC signing context.
  * \param data       Pointer to data to be added.
@@ -116,7 +127,7 @@ int knot_dnssec_sign_add(knot_dnssec_sign_context_t *context,
                          const uint8_t *data, size_t data_size);
 
 /**
- * \brief Finish DNSSEC signing and write out the signature.
+ * \brief Write down the DNSSEC signature for supplied data.
  *
  * \param context    DNSSEC signing context.
  * \param signature  Pointer to signature to be written.
@@ -127,15 +138,18 @@ int knot_dnssec_sign_write(knot_dnssec_sign_context_t *context,
                            uint8_t *signature);
 
 /**
- * \brief Clean DNSSEC signing context to start a new signature.
- *
- * Need not be called after knot_dnssec_sign_init().
+ * \brief Verify the DNSSEC signature for supplied data.
  *
- * \param context	DNSSEC signing context.
+ * \param context         DNSSEC signing context.
+ * \param signature       Signature.
+ * \param signature_size  Size of the signature.
  *
- * \return Error code, KNOT_EOK if successful.
+ * \return Error code.
+ * \retval KNOT_EOK                        The signature is valid.
+ * \retval KNOT_DNSSEC_EINVALID_SIGNATURE  The signature is not valid.
  */
-int knot_dnssec_sign_new(knot_dnssec_sign_context_t *context);
+int knot_dnssec_sign_verify(knot_dnssec_sign_context_t *context,
+                            const uint8_t *signature, size_t signature_size);
 
 #endif // _KNOT_DNSSEC_SIGN_H_