2011-07-26 46 views
13

Jestem jednostką testującą aplikację .NET; niektóre testy jednostkowe obejmują programowe generowanie obiektów X509Certificate2.Jak stworzyć minimalny manekin X509Certificate2?

Nie obchodzi mnie faktyczny podpis/klucz prywatny/sprawdzanie poprawności, chciałbym mieć obiekt, który nie generuje wyjątków podczas sprawdzania jego pól. Próbowałem użyć konstruktora bez parametrów, ale wtedy cała grupa pól wyrzuci wyjątki, gdy się do niego dostanie. Jak widać w debugerze:

SubjectName = '(nowy System.Collections.Generic.Mscorlib_CollectionDebugView (result.Certificates)). Items [0] .SubjectName "rzucił wyjątek typu" System.Security.Cryptography.CryptographicException "

próbowałem też przekazując tablicę bajtów z niektórych liczb losowych w nim, ale to nie miało nawet skonstruować

Więc pytanie (czy tablica musi być konkretny rozmiar): co jest najprostszym (najmniej linii kodu) sposób programowo wygenerować obiekt X509Certificate2, który nie będzie generował wyjątków po uzyskaniu dostępu do pola/nieruchomości?

+0

Co jest Moli? Czy możesz podać ostateczne rozwiązanie jako odpowiedź? Próbuję zrobić to samo teraz. – Langdon

+0

Zakładam, że oznacza on framework do tworzenia skrótów testowych i objazdów z badań Microsoftu. Możesz zajrzeć tutaj: http://research.microsoft.com/en-us/projects/moles/. – Sascha

Odpowiedz

8

Proponuję następujące:

  1. Generowanie certyfikatu przy użyciu makecert.
  2. Dodaj certyfikat do projektu i zmień jego działanie kompilacyjne na osadzone zasoby.
  3. Załaduj certyfikat z zasobu do konfiguracji testu urządzenia, patrz poniżej.

Kod:

byte[] embeddedCert; 
Assembly thisAssembly = Assembly.GetAssembly(typeof(MyType)); 
using (Stream certStream = thisAssembly.GetManifestResourceStream("YourProjectName.localhost.pfx")) 
{ 
    embeddedCert = new byte[certStream.Length]; 
    certStream.Read(embeddedCert, 0, (int)certStream.Length); 
} 

_signingCert = new X509Certificate2(embeddedCert, "password"); 

W tym momencie powinno być dobrze iść tak daleko, jak interakcji z certyfikatem. Możesz tworzyć różne warianty, jeśli twoje testy jednostkowe mają inne potrzeby.

+1

Przypuszczam, że mógłbym po prostu odczytać tablicę bajtów * raz *, wydrukować ją w pliku jako znaki, a następnie skopiować i wkleić do kodu źródłowego jako zakodowany bajt []? To nie byłoby tak źle ... – Cephron

+0

Tak, to też by działało. –

+0

Skończyło się używanie Moli, aby działało, ale dziękuję za pomocną odpowiedź! – Cephron

1

Na życzenie Langdona, rozwiązanie Kiedyś, sobie:

 //Moling test Certificate 
     var cert = new MX509Certificate2(); 
     var subject = new MX500DistinguishedName(); 
     // hookup 
     cert.SubjectNameGet =() => subject; 
     cert.ThumbprintGet =() => "foo"; 
     subject.NameGet =() => "foobar"; 

To działało, bo tylko pola I obejrzano w świadectwie były to SubjectName i Thumbprint, a jedynym obszarem na SubjectName I dostęp był Nazwa. I "spopielałem" metody gettera dla tych pól, aby zwrócić łańcuchy fikcyjne. Jeśli chcesz uzyskać dostęp do innych pól, prawdopodobnie będziesz musiał je przekierować.

Co to jest "Moles"?

"Moles jest lekką platformą dla skrótów testowych i objazdów w platformie .NET, która jest oparta na delegatach Moles może być używana do objazdu dowolnej metody .NET, w tym metod nie-wirtualnych/statycznych w zaplombowanych typach. w Visual Studio Gallery lub w pakiecie z Pex. "

http://research.microsoft.com/en-us/projects/moles/

+1

Przyjąłem odpowiedź Jasona nad moją, ponieważ jego jest bardziej ogólny. – Cephron

2

To może wydawać się bardzo hacky, a to zależy od tego, jak pragmatyczne chcesz być ... podejście Kiedyś było po prostu chwyć losowe certyfikat z maszyny.

To było dobre, gdy: - Wiem, że każda maszyna, która przeprowadza te testy, ma ważny certyfikat. - Korzystałem z GIT i nie chciałem sprawdzać pliku binarnego dla certyfikatu - Nie interesuje mnie treść certyfikatu - Używam kodu, który nie jest kpiąco przyjazny i wyraźnie wymaga niezasłaniającego certyfikatu X509 obiekt.

Zdecydowanie nie jest to punktowy, ale odblokowałem mnie i odblokowałem scenariusz testowy.

static X509Certificate2 GetRandomCertificate() 
    { 
     X509Store st = new X509Store(StoreName.My, StoreLocation.LocalMachine); 
     st.Open(OpenFlags.ReadOnly); 
     try 
     { 
      var certCollection = st.Certificates; 

      if (certCollection.Count == 0) 
      { 
       return null; 
      } 
      return certCollection[0]; 
     } 
     finally 
     { 
      st.Close(); 
     } 
    } 
+1

To jest świetne do testowania. Czy tak przy okazji, musimy strzec się haseł? – Timo

0

Jest jeszcze jeden prosty sposób na zrobienie tego.

  1. Utwórz certyfikat za pomocą programu MakeCert lub wyeksportuj istniejący certyfikat.
  2. Dodaj certyfikat do projektu (folder App_Data).
  3. Wykonaj poniższe czynności, aby uzyskać certyfikat.

Kod:

 string certificate = "cert.pfx"; 
     string certPath = string.Format("{0}/App_Data/{1}", HttpRuntime.AppDomainAppPath, certificate); 
     byte[] bytes = Util.FileToArray(certPath); 
     X509Certificate2 publicKey = new X509Certificate2(bytes, "somepassoword");