Change how static static keys are added for sending
diff --git a/src/Cose.c b/src/Cose.c
index 612f761..3b18219 100644
--- a/src/Cose.c
+++ b/src/Cose.c
@@ -328,10 +328,6 @@
 		break;
 
 	case COSE_DONT_SEND:
-		if (pCose->m_dontSendMap == NULL) {
-			pCose->m_dontSendMap = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &error);
-			CHECK_CONDITION(pCose->m_dontSendMap != NULL, COSE_ERR_OUT_OF_MEMORY);
-		}
 		f = cn_cbor_mapput_int(pCose->m_dontSendMap, key, value, CBOR_CONTEXT_PARAM_COMMA &error);
 		break;
 
diff --git a/src/Recipient.c b/src/Recipient.c
index 63b659b..f7ba63e 100644
--- a/src/Recipient.c
+++ b/src/Recipient.c
@@ -128,7 +128,8 @@
 *
 * @param[in]	COSE *		Pointer to COSE Encryption context object
 * @param[in]	int			Alorithm key is being generated for
-* @param[in]	cn_cbor *	Key used for operation
+* @param[in]	cn_cbor *	Private key
+* @param[in]	cn_cbor *	Public Key
 * @param[out]	byte *		Buffer to return new key in	
 * @param[in]	size_t       Size of key to create in bits
 * @param[in]    size_t		Size of digest function
@@ -137,7 +138,7 @@
 * @return                   Did the function succeed?
 */
 
-static bool HKDF_X(COSE * pCose, bool fHMAC, bool fECDH, bool fStatic, bool fSend, int algResult, const cn_cbor * pKey, byte * pbKey, size_t cbitKey, size_t cbitHash, CBOR_CONTEXT_COMMA cose_errback * perr)
+static bool HKDF_X(COSE * pCose, bool fHMAC, bool fECDH, bool fStatic, bool fSend, int algResult, const cn_cbor * pKeyPrivate, const cn_cbor * pKeyPublic, byte * pbKey, size_t cbitKey, size_t cbitHash, CBOR_CONTEXT_COMMA cose_errback * perr)
 {
 	byte * pbContext = NULL;
 	size_t cbContext;
@@ -150,30 +151,51 @@
 
 	if (!BuildContextBytes(pCose, algResult, cbitKey, &pbContext, &cbContext, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
-	cn = cn_cbor_mapget_int(pKey, COSE_Key_Type);
-	CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
 
 	if (fECDH) {
 		cn_cbor * pkeyMessage;
 
-		pkeyMessage = _COSE_map_get_int(pCose, fStatic ? COSE_Header_ECDH_STATIC : COSE_Header_ECDH_EPHEMERAL, COSE_BOTH, perr);
+		if (pKeyPrivate != NULL) {
+			cn = cn_cbor_mapget_int(pKeyPrivate, COSE_Key_Type);
+			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
+			CHECK_CONDITION(cn->v.uint == COSE_Key_Type_EC2, COSE_ERR_INVALID_PARAMETER);
+		}
 
-		CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+		if (pKeyPublic != NULL) {
+			cn = cn_cbor_mapget_int(pKeyPublic, COSE_Key_Type);
+			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
+			CHECK_CONDITION(cn->v.uint == COSE_Key_Type_EC2, COSE_ERR_INVALID_PARAMETER);
+		}
+
 		if (fSend) {
-			if (!ECDH_ComputeSecret(pCose, &pkeyMessage, pKey, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+			CHECK_CONDITION(pKeyPublic != NULL, COSE_ERR_INVALID_PARAMETER);
+			pkeyMessage = pKeyPrivate;
+
+			if (!ECDH_ComputeSecret(pCose, &pkeyMessage, pKeyPublic, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 			if (pkeyMessage->parent == NULL) {
 				if (!_COSE_map_put(pCose, COSE_Header_ECDH_EPHEMERAL, pkeyMessage, COSE_UNPROTECT_ONLY, perr)) goto errorReturn;
 			}
 		}
 		else {
+
+			pkeyMessage = _COSE_map_get_int(pCose, fStatic ? COSE_Header_ECDH_STATIC : COSE_Header_ECDH_EPHEMERAL, COSE_BOTH, perr);
+
 			CHECK_CONDITION(pkeyMessage != NULL, COSE_ERR_INVALID_PARAMETER);
-			if (!ECDH_ComputeSecret(pCose, (cn_cbor **)&pKey, pkeyMessage, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+			CHECK_CONDITION(pKeyPrivate != NULL, COSE_ERR_INVALID_PARAMETER);
+
+			if (!ECDH_ComputeSecret(pCose, (cn_cbor **)&pKeyPrivate, pkeyMessage, &pbSecret, &cbSecret, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		}
 	}
 	else {
+		if (pKeyPrivate != NULL) {
+			cn = cn_cbor_mapget_int(pKeyPrivate, COSE_Key_Type);
+			CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);
+			CHECK_CONDITION(cn->v.uint == COSE_Key_Type_OCTET, COSE_ERR_INVALID_PARAMETER);
+		}
+
 		CHECK_CONDITION(cn->v.sint == 4, COSE_ERR_INVALID_PARAMETER);
 
-		cn = cn_cbor_mapget_int(pKey, -1);
+		cn = cn_cbor_mapget_int(pKeyPrivate, -1);
 		CHECK_CONDITION((cn != NULL) && (cn->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 		pbSecret = (byte *) cn->v.bytes;
 		cbSecret = cn->length;
@@ -299,74 +321,74 @@
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
-		if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
-		if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_AES_128:
-		if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_AES_256:
-		if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, false, false, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_HKDF_256:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_HKDF_512:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_HKDF_256:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_HKDF_512:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, algIn, pRecip->m_pkey, NULL, pbKey, cbitKey, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A128KW:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, NULL, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 128, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A192KW:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, NULL, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 192, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A256KW:
-		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, false, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, NULL, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 256, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A128KW:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_128, pRecip->m_pkey, NULL, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 128, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A192KW:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_192, pRecip->m_pkey, NULL, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 192, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A256KW:
-		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pcose->m_message, true, true, true, false, COSE_Algorithm_AES_KW_256, pRecip->m_pkey, NULL, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 
 		if (!AES_KW_Decrypt((COSE_Enveloped *)pcose, rgbKey, 256, cnBody->v.bytes, cnBody->length, pbKey, &cbKey2, perr)) goto errorReturn;
 
@@ -518,32 +540,32 @@
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A128KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_128, pRecipient->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_128, NULL, pRecipient->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 128, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A192KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_192, pRecipient->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_192, NULL, pRecipient->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 192, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_A256KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_256, pRecipient->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, COSE_Algorithm_AES_KW_256, NULL, pRecipient->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 256, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A128KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_128, pRecipient->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_128, pRecipient->m_pkeyStatic, pRecipient->m_pkey, rgbKey, 128, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 128, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A192KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_192, pRecipient->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_192, pRecipient->m_pkeyStatic, pRecipient->m_pkey, rgbKey, 192, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 192, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_A256KW:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_256, pRecipient->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, COSE_Algorithm_AES_KW_256, pRecipient->m_pkeyStatic, pRecipient->m_pkey, rgbKey, 256, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		if (!AES_KW_Encrypt(pRecipient, rgbKey, 256, pbContent, (int)cbContent, perr)) goto errorReturn;
 		break;
 
@@ -603,35 +625,35 @@
 	break;
 
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_256:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, false, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, false, false, true, algIn, pRecipient->m_pkey, NULL, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_HMAC_SHA_512:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, false, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, false, false, true, algIn, pRecipient->m_pkey, NULL, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_AES_128:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, false, false, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, false, false, false, true, algIn, pRecipient->m_pkey, NULL, pb, cbitKeySize, 128, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_Direct_HKDF_AES_256:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, false, false, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, false, false, false, true, algIn, pRecipient->m_pkey, NULL, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_HKDF_256:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, algIn, NULL, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_ES_HKDF_512:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, false, true, algIn, NULL, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_HKDF_256:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, algIn, pRecipient->m_pkeyStatic, pRecipient->m_pkey, pb, cbitKeySize, 256, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	case COSE_Algorithm_ECDH_SS_HKDF_512:
-		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, algIn, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
+		if (!HKDF_X(&pRecipient->m_encrypt.m_message, true, true, true, true, algIn, pRecipient->m_pkeyStatic, pRecipient->m_pkey, pb, cbitKeySize, 512, CBOR_CONTEXT_PARAM_COMMA perr)) goto errorReturn;
 		break;
 
 	default:
@@ -746,6 +768,97 @@
 }
 
 /*!
+* @brief Set the senders static key for ECDH key agreement algorithms
+*
+* Set the Static private key to be used in computing ECDH key agreement
+* operation.  
+*
+* Private portion of the key is not zeroed when the recipient object is
+* released.
+*
+* @param h  Handle to the recipient object
+* @param pKey pointer to COSE key structure contiaing the private key
+* @param destination 0 - set nothing, 1 - set spk_kid, 2 - set spk
+* @param perr location for return of error code
+* @return true on success
+*/
+
+bool COSE_Recipient_SetSenderKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, int destination, cose_errback * perr)
+{
+	COSE_RecipientInfo * p;
+	bool f = false;
+	cn_cbor * cn;
+	cn_cbor * cn2 = NULL;
+	cn_cbor * cn3 = NULL;
+	cn_cbor_errback cbor_err;
+#ifdef USE_CBOR_CONTEXT
+	cn_cbor_context * context;
+#endif;
+
+	CHECK_CONDITION(IsValidRecipientHandle(h), COSE_ERR_INVALID_HANDLE);
+	CHECK_CONDITION(pKey != NULL, COSE_ERR_INVALID_PARAMETER);
+
+	p = (COSE_RecipientInfo *)h;
+
+#ifdef USE_CBOR_CONTEXT
+	context = &p->m_encrypt.m_message.m_allocContext;
+#endif
+
+	switch (destination) {
+	case 0:
+		break;
+
+	case 1:
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_ID);
+		CHECK_CONDITION(cn != NULL, COSE_ERR_INVALID_PARAMETER);
+		cn2 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn2 != NULL, cbor_err);
+		CHECK_CONDITION(_COSE_map_put(&p->m_encrypt.m_message, COSE_Header_ECDH_SPK_KID, cn2, COSE_UNPROTECT_ONLY, perr), perr->err);
+		cn2 = NULL;
+		break;
+
+	case 2:
+		cn2 = cn_cbor_map_create(CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn2 != NULL, cbor_err);
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_Type);
+		CHECK_CONDITION(cn != NULL, COSE_ERR_INVALID_PARAMETER);
+		cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_Type, cn3, CBOR_CONTEXT_PARAM_COMMA &cbor_err), cbor_err);
+		cn3 = NULL;
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_Curve);
+		cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_Curve, cn3, CBOR_CONTEXT_PARAM_COMMA &cbor_err), cbor_err);
+		cn3 = NULL;
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_X);
+		cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_X, cn3, CBOR_CONTEXT_PARAM_COMMA &cbor_err), cbor_err);
+		cn3 = NULL;
+		cn = cn_cbor_mapget_int(pKey, COSE_Key_EC2_Y);
+		cn3 = cn_cbor_clone(cn, CBOR_CONTEXT_PARAM_COMMA &cbor_err);
+		CHECK_CONDITION_CBOR(cn3 != NULL, cbor_err);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(cn2, COSE_Key_EC2_Y, cn3, CBOR_CONTEXT_PARAM_COMMA &cbor_err), cbor_err);
+		cn3 = NULL;
+		CHECK_CONDITION(_COSE_map_put(&p->m_encrypt.m_message, COSE_Header_ECDH_SPK, cn2, COSE_UNPROTECT_ONLY, perr), perr->err);
+		cn2 = NULL;
+		break;
+
+	default:
+		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
+	}
+
+	p->m_pkeyStatic = pKey;
+
+	f = true;
+errorReturn:
+	if (cn2 != NULL) CN_CBOR_FREE(cn2, context);
+	if (cn3 != NULL) CN_CBOR_FREE(cn3, context);
+	return f;
+}
+
+/*!
 * @brief Set the application external data for authentication
 *
 * Recipient data objects support the authentication of external application
diff --git a/src/cose.h b/src/cose.h
index 7232bb6..2df6954 100644
--- a/src/cose.h
+++ b/src/cose.h
@@ -153,15 +153,22 @@
 	COSE_Header_UseCompressedECDH = -997,
 
 	COSE_Header_ECDH_EPHEMERAL = -1,
-	COSE_Header_ECDH_STATIC = -2
+	COSE_Header_ECDH_STATIC = -2,
+	COSE_Header_ECDH_EPK = -1,
+	COSE_Header_ECDH_SPK = -2,
+	COSE_Header_ECDH_SPK_KID = -2,
 
 } COSE_Header;
 
 typedef enum {
 	COSE_Key_Type_EC2 = 2,
+	COSE_Key_Type_OCTET = 4,
 	COSE_Key_Type = 1,
 	COSE_Key_ID = 2,
 	COSE_Parameter_KID = 4,
+	COSE_Key_EC2_Curve=-1,
+	COSE_Key_EC2_X = -2,
+	COSE_Key_EC2_Y = -3
 } COSE_Constants;
 
 
@@ -197,6 +204,7 @@
 
 bool COSE_Recipient_SetKey_secret(HCOSE_RECIPIENT h, const byte * rgb, int cb, const byte * rgbKid, int cbKid, cose_errback * perr);
 bool COSE_Recipient_SetKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, cose_errback * perror);
+bool COSE_Recipient_SetSenderKey(HCOSE_RECIPIENT h, const cn_cbor * pKey, cose_errback * perror);
 bool COSE_Recipient_SetExternal(HCOSE_RECIPIENT hcose, const byte * pbExternalData, size_t cbExternalData, cose_errback * perr);
 
 bool COSE_Recipient_map_put(HCOSE_RECIPIENT h, int key, cn_cbor * value, int flags, cose_errback * perror);
diff --git a/src/cose_int.h b/src/cose_int.h
index ead32c2..5940398 100644
--- a/src/cose_int.h
+++ b/src/cose_int.h
@@ -60,6 +60,7 @@
 	COSE_Enveloped m_encrypt;
 	COSE_RecipientInfo * m_recipientNext;
 	const cn_cbor * m_pkey;
+	const cn_cbor * m_pkeyStatic;
 };
 
 typedef struct {
diff --git a/src/openssl.c b/src/openssl.c
index 9ce333f..9a88a7d 100644
--- a/src/openssl.c
+++ b/src/openssl.c
@@ -16,6 +16,8 @@
 #include <openssl/ecdh.h>
 #include <openssl/rand.h>
 
+bool FUseCompressed = true;
+
 #define MIN(A, B) ((A) < (B) ? (A) : (B))
 
 bool AES_CCM_Decrypt(COSE_Enveloped * pcose, int TSize, int LSize, const byte * pbKey, size_t cbKey, const byte * pbCrypto, size_t cbCrypto, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr)
@@ -803,16 +805,25 @@
 	CHECK_CONDITION(ecgroup != NULL, COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION(EC_KEY_set_group(pNewKey, ecgroup) == 1, COSE_ERR_CRYPTO_FAIL);
 
-	rgbKey[0] = POINT_CONVERSION_UNCOMPRESSED;
 	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_X);
 	CHECK_CONDITION((p != NULL) && (p->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
 	CHECK_CONDITION(p->length == *cbGroup, COSE_ERR_INVALID_PARAMETER);
 	memcpy(rgbKey+1, p->v.str, p->length);
 
 	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Y);
-	CHECK_CONDITION((p != NULL) && (p->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
-	CHECK_CONDITION(p->length == *cbGroup, COSE_ERR_INVALID_PARAMETER);
-	memcpy(rgbKey + p->length+1, p->v.str, p->length);
+	CHECK_CONDITION((p != NULL), COSE_ERR_INVALID_PARAMETER);
+	if (p->type == CN_CBOR_BYTES) {
+		rgbKey[0] = POINT_CONVERSION_UNCOMPRESSED;
+		CHECK_CONDITION(p->length == *cbGroup, COSE_ERR_INVALID_PARAMETER);
+		memcpy(rgbKey + p->length + 1, p->v.str, p->length);
+	}
+	else if (p->type == CN_CBOR_TRUE) {
+		rgbKey[0] = POINT_CONVERSION_COMPRESSED + 1;
+	}
+	else if (p->type == CN_CBOR_FALSE) {
+		rgbKey[0] = POINT_CONVERSION_COMPRESSED;
+	}
+	else FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
 
 	pPoint = EC_POINT_new(ecgroup);
 	CHECK_CONDITION(pPoint != NULL, COSE_ERR_CRYPTO_FAIL);
@@ -869,21 +880,42 @@
 	pPoint = EC_KEY_get0_public_key(pKey);
 	CHECK_CONDITION(pPoint != NULL, COSE_ERR_INVALID_PARAMETER);
 
-	cbSize = EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
-	CHECK_CONDITION(cbSize > 0, COSE_ERR_CRYPTO_FAIL);
-	pbOut = COSE_CALLOC(cbSize, 1, context);
-	CHECK_CONDITION(pbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
-	CHECK_CONDITION(EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED, pbOut, cbSize, NULL) == cbSize, COSE_ERR_CRYPTO_FAIL);
-
+	if (FUseCompressed) {
+		cbSize = EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL);
+		CHECK_CONDITION(cbSize > 0, COSE_ERR_CRYPTO_FAIL);
+		pbOut = COSE_CALLOC(cbSize, 1, context);
+		CHECK_CONDITION(pbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+		CHECK_CONDITION(EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_COMPRESSED, pbOut, cbSize, NULL) == cbSize, COSE_ERR_CRYPTO_FAIL);
+	}
+	else {
+		cbSize = EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+		CHECK_CONDITION(cbSize > 0, COSE_ERR_CRYPTO_FAIL);
+		pbOut = COSE_CALLOC(cbSize, 1, context);
+		CHECK_CONDITION(pbOut != NULL, COSE_ERR_OUT_OF_MEMORY);
+		CHECK_CONDITION(EC_POINT_point2oct(pgroup, pPoint, POINT_CONVERSION_UNCOMPRESSED, pbOut, cbSize, NULL) == cbSize, COSE_ERR_CRYPTO_FAIL);
+	}
 	p = cn_cbor_data_create(pbOut+1, (int) (cbSize / 2), CBOR_CONTEXT_PARAM_COMMA &cbor_error);
 	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
 	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_X, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
 	p = NULL;
 
-	p = cn_cbor_data_create(pbOut + cbSize / 2+1, (int) (cbSize / 2), CBOR_CONTEXT_PARAM_COMMA &cbor_error);
-	pbOut = NULL;   // It is already part of the other one.
+	if (FUseCompressed) {
+		p = cn_cbor_bool_create(pbOut[0] & 1, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Y, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+		p = NULL;
+	}
+	else {
+		p = cn_cbor_data_create(pbOut + cbSize / 2 + 1, (int)(cbSize / 2), CBOR_CONTEXT_PARAM_COMMA &cbor_error);
+		pbOut = NULL;   // It is already part of the other one.
+		CHECK_CONDITION_CBOR(p != NULL, cbor_error);
+		CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Y, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+		p = NULL;
+	}
+
+	p = cn_cbor_int_create(COSE_Key_Type_EC2, CBOR_CONTEXT_PARAM_COMMA &cbor_error);
 	CHECK_CONDITION_CBOR(p != NULL, cbor_error);
-	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_EC_Y, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
+	CHECK_CONDITION_CBOR(cn_cbor_mapput_int(pkey, COSE_Key_Type, p, CBOR_CONTEXT_PARAM_COMMA &cbor_error), cbor_error);
 	p = NULL;
 
 returnHere:
@@ -1078,51 +1110,65 @@
 	RAND_bytes(pb, (int) cb);
 }
 
-bool ECDH_ComputeSecret(COSE * pRecipient, cn_cbor ** ppKeyMe, const cn_cbor * pKeyYou, byte ** ppbSecret, size_t * pcbSecret, CBOR_CONTEXT_COMMA cose_errback *perr)
+/*!
+*
+* @param[in] pRecipent	Pointer to the message object
+* @param[in] ppKeyPrivate	Address of key with private portion
+* @param[in] pKeyPublic	Address of the key w/o a private portion
+* @param[in/out] ppbSecret	pointer to buffer to hold the computed secret
+* @param[in/out] pcbSecret	size of the computed secret
+* @param[in] context		cbor allocation context structure
+* @param[out] perr			location to return error information
+* @returns		success of the function
+*/
+
+bool ECDH_ComputeSecret(COSE * pRecipient, cn_cbor ** ppKeyPrivate, const cn_cbor * pKeyPublic, byte ** ppbSecret, size_t * pcbSecret, CBOR_CONTEXT_COMMA cose_errback *perr)
 {
-	EC_KEY * pkeyMe = NULL;
-	EC_KEY * pkeyYou = NULL;
+	EC_KEY * peckeyPrivate = NULL;
+	EC_KEY * peckeyPublic = NULL;
 	int cbGroup;
 	int cbsecret;
 	byte * pbsecret = NULL;
+	bool fRet = false;
 
-	pkeyYou = ECKey_From(pKeyYou, &cbGroup, perr);
-	if (pkeyYou == NULL) goto errorReturn;
+	peckeyPublic = ECKey_From(pKeyPublic, &cbGroup, perr);
+	if (peckeyPublic == NULL) goto errorReturn;
 
-	if (*ppKeyMe == NULL) {
-		pkeyMe = EC_KEY_new();
-		EC_KEY_set_group(pkeyMe, EC_KEY_get0_group(pkeyYou));
-		CHECK_CONDITION(EC_KEY_generate_key(pkeyMe) == 1, COSE_ERR_CRYPTO_FAIL);
-		*ppKeyMe = EC_FromKey(pkeyMe, CBOR_CONTEXT_PARAM_COMMA perr);
-		if (*ppKeyMe == NULL) goto errorReturn;
+	if (*ppKeyPrivate == NULL) {
+		{
+			cn_cbor * pCompress = _COSE_map_get_int(pRecipient, COSE_Header_UseCompressedECDH, COSE_BOTH, perr);
+			if (pCompress == NULL) FUseCompressed = false;
+			else FUseCompressed = (pCompress->type == CN_CBOR_TRUE);
+		}
+		peckeyPrivate = EC_KEY_new();
+		EC_KEY_set_group(peckeyPrivate, EC_KEY_get0_group(peckeyPublic));
+		CHECK_CONDITION(EC_KEY_generate_key(peckeyPrivate) == 1, COSE_ERR_CRYPTO_FAIL);
+		*ppKeyPrivate = EC_FromKey(peckeyPrivate, CBOR_CONTEXT_PARAM_COMMA perr);
+		if (*ppKeyPrivate == NULL) goto errorReturn;
 	}
 	else {
-		pkeyMe = ECKey_From(*ppKeyMe, &cbGroup, perr);
-		if (pkeyMe == NULL) goto errorReturn;
+		peckeyPrivate = ECKey_From(*ppKeyPrivate, &cbGroup, perr);
+		if (peckeyPrivate == NULL) goto errorReturn;
 	}
 
 	pbsecret = COSE_CALLOC(cbGroup, 1, context);
 	CHECK_CONDITION(pbsecret != NULL, COSE_ERR_OUT_OF_MEMORY);
 
-	cbsecret = ECDH_compute_key(pbsecret, cbGroup, EC_KEY_get0_public_key(pkeyYou), pkeyMe, NULL);
+	cbsecret = ECDH_compute_key(pbsecret, cbGroup, EC_KEY_get0_public_key(peckeyPublic), peckeyPrivate, NULL);
 	CHECK_CONDITION(cbsecret > 0, COSE_ERR_CRYPTO_FAIL);
 
 	*ppbSecret = pbsecret;
 	*pcbSecret = cbsecret;
 	pbsecret = NULL;
 
-	if (pkeyMe != NULL) EC_KEY_free(pkeyMe);
-	if (pkeyYou != NULL) EC_KEY_free(pkeyYou);
-
-	return true;
+	fRet = true;
 
 errorReturn:
 	if (pbsecret != NULL) COSE_FREE(pbsecret, context);
-	if (pkeyMe != NULL) EC_KEY_free(pkeyMe);
-	if (pkeyYou != NULL) EC_KEY_free(pkeyYou);
+	if (peckeyPublic != NULL) EC_KEY_free(peckeyPublic);
+	if (peckeyPrivate != NULL) EC_KEY_free(peckeyPrivate);
 
-	return false;
-
+	return fRet;
 }
 
 #endif // USE_OPEN_SSL
diff --git a/test/context.c b/test/context.c
index 3546f04..dbdea88 100644
--- a/test/context.c
+++ b/test/context.c
@@ -1,4 +1,6 @@
 #include <stdlib.h>
+#ifdef _MSC_VER
+#endif
 #include <stdio.h>
 #include <memory.h>
 #include <assert.h>
diff --git a/test/encrypt.c b/test/encrypt.c
index 0cf8193..53d0103 100644
--- a/test/encrypt.c
+++ b/test/encrypt.c
@@ -141,6 +141,12 @@
 
 		if (!COSE_Enveloped_AddRecipient(hEncObj, hRecip, NULL)) goto returnError;
 
+		cn_cbor * pSenderKey = cn_cbor_mapget_string(pRecipients, "sender_key");
+		if (pSenderKey != NULL) {
+			cn_cbor * pSendKey = BuildKey(pSenderKey, false);
+			if (!COSE_Recipient_SetSenderKey(hRecip, pSendKey, 2, NULL)) goto returnError;
+		}
+
 		COSE_Recipient_Free(hRecip);
 	}
 
diff --git a/test/mac_test.c b/test/mac_test.c
index dc8ef1c..35014c5 100644
--- a/test/mac_test.c
+++ b/test/mac_test.c
@@ -135,6 +135,12 @@
 
 		if (!COSE_Recipient_SetKey(hRecip, pkey, NULL))goto returnError;
 
+		cn_cbor * pSenderKey = cn_cbor_mapget_string(pRecipients, "sender_key");
+		if (pSenderKey != NULL) {
+			cn_cbor * pSendKey = BuildKey(pSenderKey, false);
+			if (!COSE_Recipient_SetSenderKey(hRecip, pSendKey, 2, NULL)) goto returnError;
+		}
+
 		if (!COSE_Mac_AddRecipient(hMacObj, hRecip, NULL)) goto returnError;
 
 		COSE_Recipient_Free(hRecip);
diff --git a/test/test.c b/test/test.c
index 37bc301..823ed4d 100644
--- a/test/test.c
+++ b/test/test.c
@@ -28,7 +28,7 @@
 	int    i;
 } NameMap;
 
-NameMap RgAlgorithmNames[46] = {
+NameMap RgAlgorithmNames[47] = {
 	{"HS256", COSE_Algorithm_HMAC_256_256},
 	{"HS256/64", COSE_Algorithm_HMAC_256_64},
 	{"HS384", COSE_Algorithm_HMAC_384_384},
@@ -62,6 +62,7 @@
 	{"ECDH-ES", COSE_Algorithm_ECDH_ES_HKDF_256},
 {"ECDH-ES-512",COSE_Algorithm_ECDH_ES_HKDF_512},
 { "ECDH-SS", COSE_Algorithm_ECDH_SS_HKDF_256 },
+{ "ECDH-SS-256", COSE_Algorithm_ECDH_SS_HKDF_256}, 
 { "ECDH-SS-512",COSE_Algorithm_ECDH_SS_HKDF_512 },
 { "ECDH-ES+A128KW", COSE_Algorithm_ECDH_ES_A128KW },
 { "ECDH-ES+A192KW", COSE_Algorithm_ECDH_ES_A192KW },