상세 컨텐츠

본문 제목

테스트 인증서 생성 및 검증

.Net General

by 탑~! 2013. 5. 31. 17:34

본문

인증서 생성

1. CMD Shell 실행

2. makecert -sr LocalMachine -r -pe -n "CN=인증서 주체 명" -sky exchange -ss my

옵션 원본 rul : http://msdn.microsoft.com/ko-kr/library/bfsktky3(VS.80).aspx

-nx509name

주체의 인증서 이름을 지정합니다. 이 이름은 X.500 표준에 맞아야 합니다. 가장 간단한 방법은 이름 앞에 CN=을 붙여 큰따옴표로 묶는 것입니다(예: "CN=myName").

-pe

생성된 개인 키를 내보낼 수 있도록 표시합니다. 이렇게 하면 개인 키를 인증서에 포함할 수 있습니다.

-skkeyname

주체의 개인 키가 들어 있는 키 컨테이너 위치를 지정합니다. 키 컨테이너가 없으면 키 컨테이너가 새로 만들어집니다.

-sr location

주체의 인증서 저장소 위치를 지정합니다. Location으로currentuser(기본값)와 localmachine 중 하나를 사용할 수 있습니다.

-ssstore

주체의 출력 인증서를 저장하는 인증서 저장소 이름을 지정합니다.

-# number

1부터 2,147,483,647까지의 일련 번호를 지정합니다. 기본값은 Makecert.exe에서 생성한 고유 값입니다.

-$ authority

인증서의 서명 기관을 지정합니다. commercial(상업적 소프트웨어 게시자가 사용하는 인증서의 경우)과 individual(개인 소프트웨어 게시자가 사용하는 인증서의 경우) 중 하나로 설정해야 합니다.

-?

이 도구의 명령 구문 및 기본 옵션 목록을 표시합니다.

-!

이 도구의 명령 구문 및 확장 옵션 목록을 표시합니다.

-a algorithm

서명 알고리즘을 지정합니다. md5(기본값) 또는 sha1 중 하나로 설정해야 합니다.

-bmm/dd/yyyy

유효 기간의 시작 날짜를 지정합니다. 기본값은 해당 인증서의 작성 날짜로 설정됩니다.

-cycertType

인증서 종류를 지정합니다. 유효한 값은 end(최종 엔터티의 경우),authority(인증 기관의 경우)입니다.

-dname

주체의 이름을 표시합니다.

-emm/dd/yyyy

유효 기간의 끝 날짜를 지정합니다. 기본값은 12/31/2039 11:59:59 GMT로 설정됩니다.

-ekuoid[,oid]

향상된 키 용도 OID(개체 식별자) 목록을 쉼표로 구분하여 인증서에 삽입합니다.

-h number

해당 인증서 아래 트리의 최대 높이를 지정합니다.

-ic file

발급자의 인증서 파일을 지정합니다.

-ikkeyName

발급자의 키 컨테이너 이름을 지정합니다.

-ikykeytype

발급자의 키 형식을 지정합니다. 공급자 형식을 나타내는signature, exchange, 정수 중 하나여야 합니다. 기본적으로 교환 키에 1을, 서명 키에 2를 전달할 수 있습니다.

-in name

발급자의 인증서 일반 이름을 지정합니다.

-ipprovider

발급자의 CryptoAPI 공급자 이름을 지정합니다.

-ir location

발급자의 인증서 저장소 위치를 지정합니다. Location으로currentuser(기본값)와 localmachine 중 하나를 사용할 수 있습니다.

-isstore

발급자의 인증서 저장소 이름을 지정합니다.

-ivpvkFile

발급자의 개인 키(.pvk) 파일을 지정합니다.

-iypvkFile

발급자의 CryptoAPI 공급자 종류를 지정합니다.

-llink

정책 정보에 연결합니다(예: URL).

-m number

인증서 유효 기간을 월 단위로 지정합니다.

-nscp

Netscape 클라이언트의 권한 부여 확장을 포함합니다.

-r

자체 서명 인증서를 만듭니다.

-sc file

주체의 인증서 파일을 지정합니다.

-skykeytype

주체의 키 형식을 지정합니다. 공급자 형식을 나타내는 signature,exchange, 정수 중 하나여야 합니다. 기본적으로 교환 키에 1을, 서명 키에 2를 전달할 수 있습니다.

-spprovider

주체의 CryptoAPI 공급자 이름을 지정합니다.

-svpvkFile

주체의 개인 키(.pvk) 파일을 지정합니다. 개인 키 파일이 하나도 없으면 새로 만들어집니다.

-sy type

주체의 CryptoAPI 공급자 종류를 지정합니다.

3. mmc 실행

4. 파일(F) >> 스냅샷 추가/제거

5. 사용 가능한 스냅인에서 인증서 선택 >> 추가(A) 클릭 >> 확인

     추가시 옵션 : 스냅인이 항상 관리할 인증서 대상 (컴퓨터 계정) >> 다은 버튼 >> 

     스냅인이 항상 관리할 대상(로컬컴퓨터) >> 마침 버튼

6. Left Tree Menu에서 인증서(로컬 컴퓨터) >> 개인용 >> 인증서 선택

7. 위에서 생성한 인증서 우클릭 >> 모든 작업 >> 내보내기

    내보내기 옵션 : 인증서와 함께 개인 키를 내보내시겠습니까?(아니오) >> 다음 버튼 >>

                                  사용할 형식(DER로 인코딩된 X509 바이너리(.CER) >> 다은 버튼 >> 파일 경로 및 명 설정

8. Left Tree Menu에서 인증서(로컬 컴퓨터) >> 신뢰할 수 있는 루트 인증 기관 >> 인증서 폴더 우클릭

9. Context Menu에서 모든작업 >> 가져오기 선택

10. 다음 버튼 >> 내보낸 파일 선택 >>

       인증서 저장 위치(모든 인증서를 다음 저장장소에 저장 [신뢰할 수 있는 루트 인증 기관]) 다음 버튼 >> 마침 버튼

확인 Sample Source (c#)

- Client

public class SslTcpClient
        {
            private static Hashtable certificateErrors = new Hashtable();

            // The following method is invoked by the RemoteCertificateValidationDelegate.
            public static bool ValidateServerCertificate(
                  object sender,
                  X509Certificate certificate,
                  X509Chain chain,
                  SslPolicyErrors sslPolicyErrors)
            {
                if (sslPolicyErrors == SslPolicyErrors.None)
                    return true;

                Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

                // Do not allow this client to communicate with unauthenticated servers.
                return false;
            }
            public static void RunClient(string machineName, string serverName)
            {
                // Create a TCP/IP client socket.
                // machineName is the host running the server application.
                TcpClient client = new TcpClient(machineName, 9000);
                Console.WriteLine("Client connected.");
                // Create an SSL stream that will close the client's stream.
                SslStream sslStream = new SslStream(
                    client.GetStream(),
                    false,
                    new RemoteCertificateValidationCallback(ValidateServerCertificate),
                    null
                    );
                // The server name must match the name on the server certificate.
                try
                {
                    sslStream.AuthenticateAsClient(/*Application.StartupPath + "\\" + */serverName);
                }
                catch (AuthenticationException e)
                {
                    Console.WriteLine("Exception: {0}", e.Message);
                    if (e.InnerException != null)
                    {
                        Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                    }
                    Console.WriteLine("Authentication failed - closing the connection.");
                    client.Close();
                    return;
                }
                // Encode a test message into a byte array.
                // Signal the end of the message using the "<EOF>".
                byte[] messsage = Encoding.UTF8.GetBytes("Hello from the client.<EOF>");
                // Send hello message to the server. 
                sslStream.Write(messsage);
                sslStream.Flush();
                // Read message from the server.
                string serverMessage = ReadMessage(sslStream);
                Console.WriteLine("Server says: {0}", serverMessage);
                // Close the client connection.
                client.Close();
                Console.WriteLine("Client closed.");
            }
            static string ReadMessage(SslStream sslStream)
            {
                // Read the  message sent by the server.
                // The end of the message is signaled using the
                // "<EOF>" marker.
                byte[] buffer = new byte[2048];
                StringBuilder messageData = new StringBuilder();
                int bytes = -1;
                do
                {
                    bytes = sslStream.Read(buffer, 0, buffer.Length);

                    // Use Decoder class to convert from bytes to UTF8
                    // in case a character spans two buffers.
                    Decoder decoder = Encoding.UTF8.GetDecoder();
                    char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                    decoder.GetChars(buffer, 0, bytes, chars, 0);
                    messageData.Append(chars);
                    // Check for EOF.
                    if (messageData.ToString().IndexOf("<EOF>") != -1)
                    {
                        break;
                    }
                } while (bytes != 0);

                return messageData.ToString();
            }

            public static int Main(string[] args)
            {
                string serverCertificateName = "인증서 주체 명"; 
                string machineName = "127.0.0.1";
                SslTcpClient.RunClient(machineName, serverCertificateName);
                return 0;
            }
  }

- Server

public static int Main(string[] args)
        {
            string certificate = "내보낸 인증서 전체 경로";            
            SslTcpServer.RunServer (certificate);
            return 0;
        } 
 }

    public sealed class SslTcpServer
    {
        static X509Certificate serverCertificate = null;
        // The certificate parameter specifies the name of the file 
        // containing the machine certificate.
        public static void RunServer(string certificate)
        {
            serverCertificate = X509Certificate.CreateFromCertFile(certificate);
            // Create a TCP/IP (IPv4) socket and listen for incoming connections.
            TcpListener listener = new TcpListener(IPAddress.Any, 9000);
            listener.Start();
            while (true)
            {
                Console.WriteLine("Waiting for a client to connect...");
                // Application blocks while waiting for an incoming connection.
                // Type CNTL-C to terminate the server.
                TcpClient client = listener.AcceptTcpClient();
                ProcessClient(client);
            }
        }
        static void ProcessClient(TcpClient client)
        {
            // A client has connected. Create the 
            // SslStream using the client's network stream.
            SslStream sslStream = new SslStream(
                client.GetStream(), false);
            // Authenticate the server but don't require the client to authenticate.
            try
            {
                sslStream.AuthenticateAsServer(serverCertificate,
                    false, SslProtocols.Tls, true);
                // Display the properties and settings for the authenticated stream.
                DisplaySecurityLevel(sslStream);
                DisplaySecurityServices(sslStream);
                DisplayCertificateInformation(sslStream);
                DisplayStreamProperties(sslStream);

                // Set timeouts for the read and write to 5 seconds.
                sslStream.ReadTimeout = 5000;
                sslStream.WriteTimeout = 5000;
                // Read a message from the client.   
                Console.WriteLine("Waiting for client message...");
                string messageData = ReadMessage(sslStream);
                Console.WriteLine("Received: {0}", messageData);

                // Write a message to the client.
                byte[] message = Encoding.UTF8.GetBytes("Hello from the server.<EOF>");
                Console.WriteLine("Sending hello message.");
                sslStream.Write(message);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine("Exception: {0}", e.Message);
                if (e.InnerException != null)
                {
                    Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
                }
                Console.WriteLine("Authentication failed - closing the connection.");
                sslStream.Close();
                client.Close();
                return;
            }
            finally
            {
                // The client stream will be closed with the sslStream
                // because we specified this behavior when creating
                // the sslStream.
                sslStream.Close();
                client.Close();
            }
        }
        static string ReadMessage(SslStream sslStream)
        {
            // Read the  message sent by the client.
            // The client signals the end of the message using the
            // "<EOF>" marker.

            byte[] buffer = new byte[2048];
            StringBuilder messageData = new StringBuilder();
            int bytes = -1;
            do
            {
                // Read the client's test message.
                bytes = sslStream.Read(buffer, 0, buffer.Length);

                // Use Decoder class to convert from bytes to UTF8
                // in case a character spans two buffers.
                Decoder decoder = Encoding.UTF8.GetDecoder();
                char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
                decoder.GetChars(buffer, 0, bytes, chars, 0);
                messageData.Append(chars);
                // Check for EOF or an empty message.
                if (messageData.ToString().IndexOf("<EOF>") != -1)
                {
                    break;
                }
            } while (bytes != 0);

            return messageData.ToString();
        }
        static void DisplaySecurityLevel(SslStream stream)
        {
            Console.WriteLine("Cipher: {0} strength {1}", stream.CipherAlgorithm, stream.CipherStrength);
            Console.WriteLine("Hash: {0} strength {1}", stream.HashAlgorithm, stream.HashStrength);
            Console.WriteLine("Key exchange: {0} strength {1}", stream.KeyExchangeAlgorithm, stream.KeyExchangeStrength);
            Console.WriteLine("Protocol: {0}", stream.SslProtocol);
        }
        static void DisplaySecurityServices(SslStream stream)
        {
            Console.WriteLine("Is authenticated: {0} as server? {1}", stream.IsAuthenticated, stream.IsServer);
            Console.WriteLine("IsSigned: {0}", stream.IsSigned);
            Console.WriteLine("Is Encrypted: {0}", stream.IsEncrypted);
        }
        static void DisplayStreamProperties(SslStream stream)
        {
            Console.WriteLine("Can read: {0}, write {1}", stream.CanRead, stream.CanWrite);
            Console.WriteLine("Can timeout: {0}", stream.CanTimeout);
        }
        static void DisplayCertificateInformation(SslStream stream)
        {
            Console.WriteLine("Certificate revocation list checked: {0}", stream.CheckCertRevocationStatus);

            X509Certificate localCertificate = stream.LocalCertificate;
            if (stream.LocalCertificate != null)
            {
                Console.WriteLine("Local cert was issued to {0} and is valid from {1} until {2}.",
                    localCertificate.Subject,
                    localCertificate.GetEffectiveDateString(),
                    localCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("Local certificate is null.");
            }
            // Display the properties of the client's certificate.
            X509Certificate remoteCertificate = stream.RemoteCertificate;
            if (stream.RemoteCertificate != null)
            {
                Console.WriteLine("Remote cert was issued to {0} and is valid from {1} until {2}.",
                    remoteCertificate.Subject,
                    remoteCertificate.GetEffectiveDateString(),
                    remoteCertificate.GetExpirationDateString());
            }
            else
            {
                Console.WriteLine("Remote certificate is null.");
            }
        }


출처 : http://blog.naver.com/PostView.nhn?blogId=kcl0951&logNo=140105914176

'.Net General' 카테고리의 다른 글

직렬화(Serializable)  (0) 2015.01.15
PublicKeyToken 정보보기  (0) 2014.03.28
Oracle and ADO.NET 지원중단.  (0) 2013.04.03
Visual Studio Korea 팀의 무료 온라인 백서 공개  (0) 2012.03.16
Google APIs Client Library for .NET  (0) 2012.03.16

관련글 더보기