2015-01-22 9 views
-2

(접근 # 2) 소프트웨어 정품 인증 메커니즘을 만들어야합니다. 그래서 나는이 계획으로 끝났습니다. App은 컴퓨터의 하드웨어를 기반으로 고유 한 ID를 만듭니다. 구매자가이 ID를 나에게 이메일로 보냅니다. 내 개인 키로 서명하고 다시 서명 된 문자열을 보냅니다. 앱이 문자열을 확인 (포함 된 공개 키로 해독하고 하드웨어 ID와 비교)합니다.라이센스를 얻기 위해 C#에서 RSA로 서명

지금까지 하드웨어 ID로 끝났으며 openssl 키 (1024 비트)를 만들었습니다. 두 파일 private.pem과 public.pem입니다.

http://www.christian-etter.de/?p=771 에 설명 된 해결 방법을 적용하려고했지만 검증은 항상 실패합니다.

코드 : 당신은 UTF-8 인코딩 된 문자열 (SignedData)로 어떤 임의의 바이트를 치료하는

private void Generate_Click(object sender, EventArgs e) 
    { 
     byte[] SignedData; 
     byte[] UnsignedData = Encoding.UTF8.GetBytes(CompID.Text); 

     using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) 
     { 
      rsa.PersistKeyInCsp = false; 
      rsa.LoadPrivateKeyPEM(PrivateKey.Text); 
      using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 
       SignedData = rsa.SignData(UnsignedData, sha1); 
      ActCode.Text = Encoding.UTF8.GetString(SignedData, 0, SignedData.Length); 
     } 
    } 

    //-------------------------------------------------------------------- 

    private void Verify_Click(object sender, EventArgs e) 
    { 
     byte[] UnsignedData = Encoding.UTF8.GetBytes(CompID.Text); 
     byte[] SignedData = Encoding.UTF8.GetBytes(ActCode.Text); 
     bool VerifOK; 

     using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider()) 
     { 
      rsa.PersistKeyInCsp = false; 
      rsa.LoadPublicKeyPEM(PublicKey.Text); 
      using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 
       VerifOK = rsa.VerifyData(UnsignedData, sha1, SignedData); 
     } 
     if (VerifOK) verif.Text = "verification ok"; 
     else verif.Text = "verification error"; 
    } 
+0

이 부분을 자세히 살펴 보지 않았지만 코드가 UTF-8로 전환하거나 텍스트 상자에 저장하는 것이 무의미한 것처럼 보인다고해서 무의식적으로 바이트를 변경한다는 것을 의미합니다. 문자열에서'byte []'로 앞뒤로가는 것은 매우 조심하지 않으면 위험합니다. 가능하다면 데이터를'byte [] '로 유지하십시오. –

+0

모든 바이트 시퀀스가 ​​유효한 UTF-8 인코딩이 아닙니다. 'Convert.To/FromBase64String'을 통해 Base64 인코딩을 사용하여'SignedData'를 처리하십시오. –

+0

@mikez 대단히 감사합니다! 나는 그것을 놓쳤다. 그 트릭을 했어! – monica

답변

1

모든 바이트 시퀀스가 ​​유효하기 때문이 올바르지 않습니다. 인코더가 유효하지 않은 바이트를 버려서 검증을 실패한 것으로 의심됩니다. 바이너리 데이터를 잃지 않고 문자열 형식으로 보존하려면 Base64 인코딩을 사용해야합니다. 그래서이 :

using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 
    SignedData = rsa.SignData(UnsignedData, sha1); 
ActCode.Text = Encoding.UTF8.GetString(SignedData, 0, SignedData.Length); 

당신이 SignedData를 얻을 수 Convert.FromBase64String를 사용할 필요가 검증 중에

using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) 
    SignedData = rsa.SignData(UnsignedData, sha1); 
ActCode.Text = Convert.ToBase64String(SignedData); 

마찬가지로된다. 서명을 위해 바이너리 형식으로 변환해야하는 문자열 데이터이기 때문에 CompID에 UTF-8을 사용하는 것이 좋습니다.