programing

Microsoft Crypto API 사용 안 함 RSAES-OAEP 키 전송 알고리즘

prostudy 2022. 5. 8. 22:04
반응형

Microsoft Crypto API 사용 안 함 RSAES-OAEP 키 전송 알고리즘

사용하고 있다.CryptEncryptMessagea를 생성하다PKCS#7감춰진 메시지사용하고 있다.szOID_NIST_AES256_CBC암호화 알고리즘으로 사용할 수 있다.

생성된 메시지는 유효한 것으로 보이지만RSAES-OAEP야생에서 지원이 제한된 키 전송 알고리즘(Thunderbird, OpenSSL SMIME Module은 다른 많은 것 중에서 지원하지 않음).

가 더 오래된 CAPIgro CAPIroto CAPI로 RSAencryption주요 수송을 위해

그렇게 할 수 있는 방법이 없을까, 만약 사용보다는 방법이 있다면 낮은 수준의 메시징 기능으로 되돌릴 수 있을 것 같다.CryptEncryptMessage하지만 낮은 수준의 기능을 사용해도 방법이 없어

코드:

CRYPT_ENCRYPT_MESSAGE_PARA EncryptMessageParams;
EncryptMessageParams.cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO);

EncryptMessageParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING;

EncryptMessageParams.ContentEncryptionAlgorithm.pszObjId = szOID_NIST_AES256_CBC;
EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.cbData = 0;
EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.pbData = 0;

EncryptMessageParams.hCryptProv = NULL;
EncryptMessageParams.pvEncryptionAuxInfo = NULL;
EncryptMessageParams.dwFlags = 0;
EncryptMessageParams.dwInnerContentType = 0;

BYTE pbEncryptedBlob[640000];
DWORD pcbEncryptedBlob = 640000;

BOOL retval =  CryptEncryptMessage(&EncryptMessageParams, cRecipientCert, pRecipCertContextArray, pbMsgText, dwMsgTextSize, pbEncryptedBlob, &pcbEncryptedBlob);

키 전송 알고리즘은 다루기가 좀 까다롭고, 그 목적에 부합하지 않을 수 있다(CAPI가 지원하기를 원한다는 점에 주목했었음).RSAencryption; 날 믿어, 나도 그럴 거야.문제의 대부분을 감지한 것 같군 - 생성된 메시지는 유효한 것으로 보이지만, 당신의 방법은 잘 작동하지 않을 수도 있고 장기적으로 전혀 작동하지 않을 수도 있는 을 사용해야 한다.

1단계 - 코드 검사

CRYPT_ENCRYPT_MESSAGE_PARA EncryptMessageParams;
EncryptMessageParams.cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO);

EncryptMessageParams.dwMsgEncodingType = PKCS_7_ASN_ENCODING;

EncryptMessageParams.ContentEncryptionAlgorithm.pszObjId = szOID_NIST_AES256_CBC;
EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.cbData = 0;
EncryptMessageParams.ContentEncryptionAlgorithm.Parameters.pbData = 0;

EncryptMessageParams.hCryptProv = NULL;
EncryptMessageParams.pvEncryptionAuxInfo = NULL;
EncryptMessageParams.dwFlags = 0;
EncryptMessageParams.dwInnerContentType = 0;

BYTE pbEncryptedBlob[640000];
DWORD pcbEncryptedBlob = 640000;

BOOL retval =  CryptEncryptMessage(&EncryptMessageParams, cRecipientCert, pRecipCertContextArray, pbMsgText, dwMsgTextSize, pbEncryptedBlob, &pcbEncryptedBlob);

꽤 기초적이군, 그렇지?비록 효율적이긴 하지만, 실제로 문제를 해결하지는 못하고 있다.이것을 보면 다음과 같다.

EncryptMessageParams.dwFlags = 0;
EncryptMessageParams.dwInnerContentType = 0;

당신은 그것이 미리 정의되어있지만 오직 의 정의에만 사용된다는 것을 알게 될 것이다.retval하지만, 나는 이것이 마이크로 최적화라고 확실히 볼 수 있었고, 코드를 다시 쓸 경우에는 별로 유용하지 않다.그러나 코드를 완전히 다시 실행하지 않고 이를 통합하기 위한 기본 단계 타격(그래서 동일한 매개 변수를 계속 사용할 수 있음)을 간략히 설명했다.

2단계 - 매개 변수 편집

그의 논평에서 언급했듯이, Crypto API는 그다지 사용자 친화적이지 않다.하지만 한정된 자원으로 훌륭하게 해내셨습니다.추가하려는 것은 키의 범위를 좁히는 데 도움이 되는 암호화 열거 공급자 입니다.이러한 기능을 효율적으로 사용하려면 Microsoft 기본 암호화 공급자 버전 1.0 또는 Microsoft 고급 암호화 공급자 버전 1.0이 있는지 확인하십시오.그렇지 않으면 다음과 같은 기능을 추가해야 한다.

DWORD cbName;
DWORD dwType;
DWORD dwIndex;
CHAR *pszName = NULL;
(regular crypt calls here)

이것은 주로 예방에 쓰인다.NTE_BAD_FLAGS오류, 비록 기술적으로는 더 낮은 수준의 선언으로 이것을 피할 수 있지만.원하는 경우 완전히 새로운 해시를 생성할 수도 있다(위의 구현이 필요한 시간/속도 계수로 확장되지 않는 경우에만 필요함).

DWORD dwBufferLen = strlen((char *)pbBuffer)+1*(0+5);
HCRYPTHASH hHash;
HCRYPTKEY hKey;
HCRYPTKEY hPubKey;
BYTE *pbKeyBlob;
BYTE *pbSignature;
DWORD dwSigLen;
DWORD dwBlobLen;
(use hash as normal w/ crypt calls and the pbKeyBlobs/Signatures)

다음 단계로 넘어가기 전에 반드시 이 코드 조각의 날짜를 변경하십시오.그렇게 쉽게 할 수 있다.

if(CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) {
     printf("CSP context acquired.\n");
}

문서화 또는 릴리스하는 경우void MyHandleError(char *s)편집하지만 실패한 사람이 빨리 오류를 잡을 수 있도록 하기 위해서입니다.

그런데, 처음 실행할 때는 디폴트가 없기 때문에 새로운 세트를 만들어야 할 것이다.멋있는 원라이너로 튀어 나올 수 있는if다음 항목:

CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)

서버 리소스의 동기화는 첫 번째 단계에서 제안했던 재작업을 수행하는 것만큼 효율적이지 않다는 점을 기억하십시오.아래에 설명하고자 하는 내용은 다음과 같다.

3단계 - 재코딩 및 다시 시작

프로그래머로서, 재코딩은 시간 낭비처럼 보일 수도 있지만, 장기적으로 분명히 도움이 될 수 있다.인코딩/동기화할 때 사용자 지정 매개 변수에서 여전히 코드를 입력해야 한다는 점을 기억하십시오. 아기처럼 코드를 모두 손으로 먹일 수는 없습니다만.기본적인 윤곽을 보여주기에 충분할 것이다.

는 당신이 특정 CSP 내에서 현재 사용자의 키 컨테이너를 다루려고 한다고 확신하고 있다. 그렇지 않다면, 나는 이것의 사용법을 잘 모르겠다.그렇지 않다면, 당신은 당신의 필요에 맞게 몇 가지 기본적인 편집을 할 수 있다.

명심해, 우린 우회할 거야CryptEncryptMessage을 이용하여CryptReleaseContext에 의해 획득된 핸들을 직접 해제한다.CryptAcquireContext기능을 발휘하다마이크로소프트의 CAC 표준은 다음과 같다.

BOOL WINAPI CryptAcquireContext(
  _Out_  HCRYPTPROV *phProv,
  _In_   LPCTSTR pszContainer,
  _In_   LPCTSTR pszProvider,
  _In_   DWORD dwProvType,
  _In_   DWORD dwFlags
);

사용자 인터페이스를 사용하는 경우 Microsoft에서 다음과 같이 꾸짖는 것을 참고하십시오.

CSP가 작동하기 위해 UI를 표시해야 할 경우 호출이 실패하고 NTE_SILENT_CONTEXT 오류 코드가 마지막 오류로 설정된다.또한 CRIPT_SILENT 플래그로 획득한 컨텍스트를 CRIPT_USER_PROTECT 플래그로 CryptGenKey에 호출하면 호출이 실패하고 CSP는 NTE_SILENT_CONTEXTER를 설정한다.

이것은 주로 서버 코드 입니다. 그리고ERROR_BUSY특히 지연 시간이 긴 연결은 여러 개일 때 새 사용자에게 표시된다.300ms 이상이면NTE_BAD_KEYSET_PARAM또는 적절한 오류도 수신되지 않은 시간 초과로 인해 호출되는 것과 유사함. (전송 문제, 나와 함께 있는 사람?)

여러 DLL(이러한 DLL로 인해 지원되지 않는 DLL)에 대해 염려하지 않는 경우NTE_PROVIDER_DLL_FAIL오류), 클라이언트가 제공하는 암호화 서비스를 얻기 위한 기본 설정은 다음과 같을 것이다(마이크로소프트의 예에서 직접 복사).

if (GetLastError() == NTE_BAD_KEYSET)
 {
   if(CryptAcquireContext(
      &hCryptProv, 
      UserName, 
      NULL, 
      PROV_RSA_FULL, 
      CRYPT_NEWKEYSET)) 
    {
      printf("A new key container has been created.\n");
    }
    else
    {
      printf("Could not create a new key container.\n");
      exit(1);
    }
  }
  else
  {
      printf("A cryptographic service handle could not be "
          "acquired.\n");
      exit(1);
   }

이것이 아무리 간단해 보일지라도, 당신은 이것을 키 교환 알고리즘(또는 당신이 이것을 다루는 다른 어떤 것이든)에 전달하는데 걸림돌이 되고 싶지 않다.대칭 세션 키(Diffie-Hellman/KEA)를 사용하지 않는 한, 교환 키페어를 사용하여 세션 키를 암호화하여 안전하게 저장하고 다른 사용자와 교환할 수 있다.

존 하워드라는 사람이 여기에서 논의된 기법을 많이 편집한 멋진 Hyper-V 원격 관리 구성 유틸리티(HVREMote)를 썼다.기본 암호와 키패어(keypar)를 사용하는 것 외에, 이를 허용하기 위해 사용할 수 있다.ANONYMOUS LOGON먼 곳의DCOM접근(접근거cscript hvremote.wsf, 구체적으로 말하면).그의 블로그에서 그의 최신 암호에서 많은 기능과 기술을 볼 수 있다.

http://blogs.technet.com/b/jhoward/

기본 사항에 대한 도움이 더 필요하면 댓글을 남기거나 사적인 대화를 요청하십시오.

결론

해싱에 대한 기본적인 서버측 방법과 클라이언트가 "크립트"를 잡는 방법을 알면 꽤 간단하지만, 전송 중에 왜 암호화를 시도했는지에 대해 의문을 갖게 될 것이다.그러나, 암호화된 클라이언트가 없다면, 암호화는 분명히 이미 해시된 것을 전송할 수 있는 유일한 안전한 방법이 될 것이다.

패킷의 암호를 해독하고 솔트를 해시할 수 있다고 주장할 수 있지만, 클라이언트를 재해시하는 데 필요한 정확한 타이밍과 순서에 따라 두 패킷을 모두 처리하고 저장해야 한다는 점을 고려하십시오.

참조URL: https://stackoverflow.com/questions/13090176/microsoft-crypto-api-disable-use-of-rsaes-oaep-key-transport-algorithm

반응형