diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index 7083b25675abdec4c7c28f04e10df4be4fd1c2a8..351ce09edaadbab5c13eaed7f527ad071e4cf0c6 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -1023,6 +1023,17 @@ enum ast_sip_contact_filter {
 	AST_SIP_CONTACT_FILTER_REACHABLE = (1 << 0),
 };
 
+/*!
+ * \brief Adds a Date header to the tdata, formatted like:
+ * Date: Wed, 01 Jan 2021 14:53:01 GMT
+ * \since 16.19.0
+ *
+ * \note There is no checking done to see if the header already exists
+ * before adding it. It's up to the caller of this function to determine
+ * if that needs to be done or not.
+ */
+void ast_sip_add_date_header(pjsip_tx_data *tdata);
+
 /*!
  * \brief Register a SIP service in Asterisk.
  *
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index 809096d0969cfec88947803df4bf403252186711..84c25594b1b78c33f5ac331386ed9e0720a4bf89 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -3285,6 +3285,18 @@ static pj_sockaddr host_ip_ipv6;
 /*! Local host address for IPv6 (string form) */
 static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN];
 
+void ast_sip_add_date_header(pjsip_tx_data *tdata)
+{
+	char date[256];
+	struct tm tm;
+	time_t t = time(NULL);
+
+	gmtime_r(&t, &tm);
+	strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
+
+	ast_sip_add_header(tdata, "Date", date);
+}
+
 static int register_service(void *data)
 {
 	pjsip_module **module = data;
diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c
index c4c091f744dc3b5c733c3c9bcd06894bb665f9db..6fe40588fdc322d583b1eaacd38a21e530c5d3e3 100644
--- a/res/res_pjsip_registrar.c
+++ b/res/res_pjsip_registrar.c
@@ -247,19 +247,6 @@ static int registrar_add_contact(void *obj, void *arg, int flags)
 	return 0;
 }
 
-/*! \brief Helper function which adds a Date header to a response */
-static void registrar_add_date_header(pjsip_tx_data *tdata)
-{
-	char date[256];
-	struct tm tm;
-	time_t t = time(NULL);
-
-	gmtime_r(&t, &tm);
-	strftime(date, sizeof(date), "%a, %d %b %Y %T GMT", &tm);
-
-	ast_sip_add_header(tdata, "Date", date);
-}
-
 static const pj_str_t path_hdr_name = { "Path", 4 };
 
 static int build_path_data(pjsip_rx_data *rdata, struct ast_str **path_str)
@@ -898,7 +885,7 @@ static void register_aor_core(pjsip_rx_data *rdata,
 	ao2_cleanup(response_contact);
 
 	/* Add the date header to the response, some UAs use this to set their date and time */
-	registrar_add_date_header(tdata);
+	ast_sip_add_date_header(tdata);
 
 	ao2_callback(contacts, 0, registrar_add_contact, tdata);
 
diff --git a/res/res_pjsip_stir_shaken.c b/res/res_pjsip_stir_shaken.c
index a90b821e553e4feadfc5aeca7bccbb74ae2af483..df2aaf0bb1266179c14bdbf28288650fa90e2108 100644
--- a/res/res_pjsip_stir_shaken.c
+++ b/res/res_pjsip_stir_shaken.c
@@ -166,7 +166,7 @@ static int stir_shaken_incoming_request(struct ast_sip_session *session, pjsip_r
 		return 0;
 	}
 
-	/* Trim "info=<" to get public key URL */
+	/* Trim "info=<" to get public cert URL */
 	strtok_r(identity_hdr_val, "<", &identity_hdr_val);
 	public_cert_url = strtok_r(identity_hdr_val, ">", &identity_hdr_val);
 	if (ast_strlen_zero(public_cert_url)) {
@@ -174,6 +174,12 @@ static int stir_shaken_incoming_request(struct ast_sip_session *session, pjsip_r
 		return 0;
 	}
 
+	/* Make sure the public URL is actually a URL */
+	if (!ast_begins_with(public_cert_url, "http")) {
+		ast_stir_shaken_add_verification(chan, caller_id, "", AST_STIR_SHAKEN_VERIFY_SIGNATURE_FAILED);
+		return 0;
+	}
+
 	algorithm = strtok_r(identity_hdr_val, ";", &identity_hdr_val);
 	if (ast_strlen_zero(algorithm)) {
 		ast_stir_shaken_add_verification(chan, caller_id, "", AST_STIR_SHAKEN_VERIFY_SIGNATURE_FAILED);
@@ -202,17 +208,20 @@ static int stir_shaken_incoming_request(struct ast_sip_session *session, pjsip_r
 	return 0;
 }
 
-static void add_identity_header(const struct ast_sip_session *session, pjsip_tx_data *tdata)
+static int add_identity_header(const struct ast_sip_session *session, pjsip_tx_data *tdata)
 {
 	static const pj_str_t identity_str = { "Identity", 8 };
 	pjsip_generic_string_hdr *identity_hdr;
 	pj_str_t identity_val;
 	pjsip_fromto_hdr *old_identity;
+	pjsip_fromto_hdr *to;
+	pjsip_sip_uri *uri;
 	char *signature;
 	char *public_cert_url;
 	struct ast_json *header;
 	struct ast_json *payload;
 	char *dumped_string;
+	RAII_VAR(char *, dest_tn, NULL, ast_free);
 	RAII_VAR(struct ast_json *, json, NULL, ast_json_free);
 	RAII_VAR(struct ast_stir_shaken_payload *, ss_payload, NULL, ast_stir_shaken_payload_free);
 	RAII_VAR(char *, encoded_header, NULL, ast_free);
@@ -222,21 +231,43 @@ static void add_identity_header(const struct ast_sip_session *session, pjsip_tx_
 
 	old_identity = pjsip_msg_find_hdr_by_name(tdata->msg, &identity_str, NULL);
 	if (old_identity) {
-		return;
+		return 0;
+	}
+
+	to = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_TO, NULL);
+	if (!to) {
+		ast_log(LOG_ERROR, "Failed to find To header while adding STIR/SHAKEN Identity header\n");
+		return -1;
+	}
+
+	uri = pjsip_uri_get_uri(to->uri);
+	if (!uri) {
+		ast_log(LOG_ERROR, "Failed to retrieve URI from To header while adding STIR/SHAKEN Identity header\n");
+		return -1;
+	}
+
+	dest_tn = ast_malloc(uri->user.slen + 1);
+	if (!dest_tn) {
+		ast_log(LOG_ERROR, "Failed to allocate memory for STIR/SHAKEN dest->tn\n");
+		return -1;
 	}
 
+	ast_copy_pj_str(dest_tn, &uri->user, uri->user.slen + 1);
+
 	/* x5u (public key URL), attestation, and origid will be added by ast_stir_shaken_sign */
-	json = ast_json_pack("{s: {s: s, s: s, s: s}, s: {s: {s: s}}}", "header", "alg", "ES256", "ppt", "shaken", "typ", "passport",
-		"payload", "orig", "tn", session->id.number.str);
+	json = ast_json_pack("{s: {s: s, s: s, s: s}, s: {s: {s: s}, s: {s: s}}}",
+		"header", "alg", "ES256", "ppt", "shaken", "typ", "passport",
+		"payload", "dest", "tn", dest_tn, "orig", "tn",
+		session->id.number.str);
 	if (!json) {
 		ast_log(LOG_ERROR, "Failed to allocate memory for STIR/SHAKEN JSON\n");
-		return;
+		return -1;
 	}
 
 	ss_payload = ast_stir_shaken_sign(json);
 	if (!ss_payload) {
 		ast_log(LOG_ERROR, "Failed to allocate memory for STIR/SHAKEN payload\n");
-		return;
+		return -1;
 	}
 
 	header = ast_json_object_get(json, "header");
@@ -245,7 +276,7 @@ static void add_identity_header(const struct ast_sip_session *session, pjsip_tx_
 	ast_json_free(dumped_string);
 	if (!encoded_header) {
 		ast_log(LOG_ERROR, "Failed to encode STIR/SHAKEN header\n");
-		return;
+		return -1;
 	}
 
 	payload = ast_json_object_get(json, "payload");
@@ -254,7 +285,7 @@ static void add_identity_header(const struct ast_sip_session *session, pjsip_tx_
 	ast_json_free(dumped_string);
 	if (!encoded_payload) {
 		ast_log(LOG_ERROR, "Failed to encode STIR/SHAKEN payload\n");
-		return;
+		return -1;
 	}
 
 	signature = (char *)ast_stir_shaken_payload_get_signature(ss_payload);
@@ -269,7 +300,7 @@ static void add_identity_header(const struct ast_sip_session *session, pjsip_tx_
 	combined_str = ast_calloc(1, combined_size);
 	if (!combined_str) {
 		ast_log(LOG_ERROR, "Failed to allocate memory for STIR/SHAKEN identity string\n");
-		return;
+		return -1;
 	}
 	snprintf(combined_str, combined_size, "%s.%s.%s;info=<%s>alg=%s;ppt=%s", encoded_header,
 		encoded_payload, signature, public_cert_url, STIR_SHAKEN_ENCRYPTION_ALGORITHM, STIR_SHAKEN_PPT);
@@ -278,10 +309,26 @@ static void add_identity_header(const struct ast_sip_session *session, pjsip_tx_
 	identity_hdr = pjsip_generic_string_hdr_create(tdata->pool, &identity_str, &identity_val);
 	if (!identity_hdr) {
 		ast_log(LOG_ERROR, "Failed to create STIR/SHAKEN Identity header\n");
-		return;
+		return -1;
 	}
 
 	pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr *)identity_hdr);
+
+	return 0;
+}
+
+static void add_date_header(const struct ast_sip_session *session, pjsip_tx_data *tdata)
+{
+	static const pj_str_t date_str = { "Date", 4 };
+	pjsip_fromto_hdr *old_date;
+
+	old_date = pjsip_msg_find_hdr_by_name(tdata->msg, &date_str, NULL);
+	if (old_date) {
+		ast_debug(3, "Found old STIR/SHAKEN date header, no need to add one\n");
+		return;
+	}
+
+	ast_sip_add_date_header(tdata);
 }
 
 static void stir_shaken_outgoing_request(struct ast_sip_session *session, pjsip_tx_data *tdata)
@@ -294,7 +341,13 @@ static void stir_shaken_outgoing_request(struct ast_sip_session *session, pjsip_
 		return;
 	}
 
-	add_identity_header(session, tdata);
+	/* If adding the Identity header fails for some reason, there's no point
+	 * adding the Date header.
+	 */
+	if ((add_identity_header(session, tdata)) != 0) {
+		return;
+	}
+	add_date_header(session, tdata);
 }
 
 static struct ast_sip_session_supplement stir_shaken_supplement = {