ここでは、「デジタル署名」を行う方法を紹介します。デジタル署名は、公開鍵暗号方式を使って電子署名を実現する方法で、デジタル署名を使うことにより、そのデータを作成したのが本人であることを証明できたり、データが改ざんされていないことを確認できたりします。デジタル署名について詳しくは、「デジタル署名:ITpro」などをご覧ください。
.NET Frameworkにはデジタル署名を行うためのクラスとして、DSACryptoServiceProviderクラス、RSACryptoServiceProviderクラス、ECDsaCngクラス(.NET Framework 3.5以降)が用意されています。DSACryptoServiceProviderクラスはDSAを、RSACryptoServiceProviderクラスはRSAを、ECDsaCngクラスはECDSAを使用します。ここでは、RSACryptoServiceProviderクラスを使った例を紹介します。
早速ですが、デジタル署名を作成、検証するメソッドの例を以下に示します。ここでは文字列のデータ(メッセージ)に付けるデジタル署名を作成するためのメソッドと、検証するためのメソッドを作成しています。
''' <summary> ''' デジタル署名を作成する ''' </summary> ''' <param name="message">署名を付けるメッセージ</param> ''' <param name="privateKey">署名に使用する秘密鍵</param> ''' <returns>作成された署名</returns> Public Shared Function CreateDigitalSignature(ByVal message As String, _ ByVal privateKey As String) As String 'メッセージをバイト型配列にして、SHA1ハッシュ値を計算 Dim msgData As Byte() = System.Text.Encoding.UTF8.GetBytes(message) Dim sha As New System.Security.Cryptography.SHA1Managed() Dim hashData As Byte() = sha.ComputeHash(msgData) 'RSACryptoServiceProviderオブジェクトの作成 Dim rsa As New System.Security.Cryptography.RSACryptoServiceProvider() '秘密鍵を使って初期化 rsa.FromXmlString(privateKey) 'RSAPKCS1SignatureFormatterオブジェクトを作成 Dim rsaFormatter As New _ System.Security.Cryptography.RSAPKCS1SignatureFormatter(rsa) '署名の作成に使用するハッシュアルゴリズムを指定 rsaFormatter.SetHashAlgorithm("SHA1") '署名を作成 Dim signedValue As Byte() = rsaFormatter.CreateSignature(hashData) 'バイト型配列を文字列に変換して返す Return System.Convert.ToBase64String(signedValue) End Function ''' <summary> ''' デジタル署名を検証する ''' </summary> ''' <param name="message">署名の付いたメッセージ</param> ''' <param name="signature">署名</param> ''' <param name="publicKey">送信者の公開鍵</param> ''' <returns>認証に成功した時はTrue。失敗した時はFalse。</returns> Public Shared Function VerifyDigitalSignature(ByVal message As String, _ ByVal signature As String, _ ByVal publicKey As String) As Boolean 'メッセージをバイト型配列にして、SHA1ハッシュ値を計算 Dim msgData As Byte() = System.Text.Encoding.UTF8.GetBytes(message) Dim sha As New System.Security.Cryptography.SHA1Managed() Dim hashData As Byte() = sha.ComputeHash(msgData) 'RSACryptoServiceProviderオブジェクトの作成 Dim rsa As New System.Security.Cryptography.RSACryptoServiceProvider() '公開鍵を使って初期化 rsa.FromXmlString(publicKey) Dim rsaDeformatter As New _ System.Security.Cryptography.RSAPKCS1SignatureDeformatter(rsa) '署名の検証に使用するハッシュアルゴリズムを指定 rsaDeformatter.SetHashAlgorithm("SHA1") '署名を検証し、結果を返す Return rsaDeformatter.VerifySignature( _ hashData, System.Convert.FromBase64String(signature)) End Function ''' <summary> ''' 公開鍵と秘密鍵を作成して返す ''' </summary> ''' <param name="publicKey">作成された公開鍵(XML形式)</param> ''' <param name="privateKey">作成された秘密鍵(XML形式)</param> Public Shared Sub CreateKeys(ByRef publicKey As String, _ ByRef privateKey As String) 'RSACryptoServiceProviderオブジェクトの作成 Dim rsa As New System.Security.Cryptography.RSACryptoServiceProvider() '公開鍵をXML形式で取得 publicKey = rsa.ToXmlString(False) '秘密鍵をXML形式で取得 privateKey = rsa.ToXmlString(True) End Sub
/// <summary> /// デジタル署名を作成する /// </summary> /// <param name="message">署名を付けるメッセージ</param> /// <param name="privateKey">署名に使用する秘密鍵</param> /// <returns>作成された署名</returns> public static string CreateDigitalSignature( string message, string privateKey) { //メッセージをバイト型配列にして、SHA1ハッシュ値を計算 byte[] msgData = System.Text.Encoding.UTF8.GetBytes(message); System.Security.Cryptography.SHA1Managed sha = new System.Security.Cryptography.SHA1Managed(); byte[] hashData = sha.ComputeHash(msgData); //RSACryptoServiceProviderオブジェクトの作成 System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(); //秘密鍵を使って初期化 rsa.FromXmlString(privateKey); //RSAPKCS1SignatureFormatterオブジェクトを作成 System.Security.Cryptography.RSAPKCS1SignatureFormatter rsaFormatter = new System.Security.Cryptography.RSAPKCS1SignatureFormatter(rsa); //署名の作成に使用するハッシュアルゴリズムを指定 rsaFormatter.SetHashAlgorithm("SHA1"); //署名を作成 byte[] signedValue = rsaFormatter.CreateSignature(hashData); //バイト型配列を文字列に変換して返す return System.Convert.ToBase64String(signedValue); } /// <summary> /// デジタル署名を検証する /// </summary> /// <param name="message">署名の付いたメッセージ</param> /// <param name="signature">署名</param> /// <param name="publicKey">送信者の公開鍵</param> /// <returns>認証に成功した時はTrue。失敗した時はFalse。</returns> public static bool VerifyDigitalSignature( string message, string signature, string publicKey) { //メッセージをバイト型配列にして、SHA1ハッシュ値を計算 byte[] msgData = System.Text.Encoding.UTF8.GetBytes(message); System.Security.Cryptography.SHA1Managed sha = new System.Security.Cryptography.SHA1Managed(); byte[] hashData = sha.ComputeHash(msgData); //RSACryptoServiceProviderオブジェクトの作成 System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(); //公開鍵を使って初期化 rsa.FromXmlString(publicKey); System.Security.Cryptography.RSAPKCS1SignatureDeformatter rsaDeformatter = new System.Security.Cryptography.RSAPKCS1SignatureDeformatter(rsa); //署名の検証に使用するハッシュアルゴリズムを指定 rsaDeformatter.SetHashAlgorithm("SHA1"); //署名を検証し、結果を返す return rsaDeformatter.VerifySignature(hashData, System.Convert.FromBase64String(signature)); } /// <summary> /// 公開鍵と秘密鍵を作成して返す /// </summary> /// <param name="publicKey">作成された公開鍵(XML形式)</param> /// <param name="privateKey">作成された秘密鍵(XML形式)</param> public static void CreateKeys(out string publicKey, out string privateKey) { //RSACryptoServiceProviderオブジェクトの作成 System.Security.Cryptography.RSACryptoServiceProvider rsa = new System.Security.Cryptography.RSACryptoServiceProvider(); //公開鍵をXML形式で取得 publicKey = rsa.ToXmlString(false); //秘密鍵をXML形式で取得 privateKey = rsa.ToXmlString(true); }
次に、上記のメソッドを使う例を示します。まず、CreateKeysメソッドで公開鍵と秘密鍵を作成します。署名を作成するには、CreateDigitalSignatureメソッドに署名を付けるメッセージと秘密鍵を指定します。署名を検証するには、VerifyDigitalSignatureメソッドにメッセージと署名と公開鍵を指定します。
'デジタル署名をつけるメッセージ Dim message As String = "あいうえお" '公開鍵と秘密鍵を取得 Dim privateKey As String = "" Dim publicKey As String = "" CreateKeys(publicKey, privateKey) '署名を作成する Dim signature As String = CreateDigitalSignature(message, privateKey) '署名を検証する If VerifyDigitalSignature(message, signature, publicKey) Then Console.WriteLine("検証成功") Else Console.WriteLine("検証失敗") End If
//デジタル署名をつけるメッセージ string message = "あいうえお"; //公開鍵と秘密鍵を取得 string privateKey; string publicKey; CreateKeys(out publicKey , out privateKey); //署名を作成する string signature = CreateDigitalSignature(message, privateKey); //署名を検証する if (VerifyDigitalSignature(message, signature, publicKey)) { Console.WriteLine("検証成功"); } else { Console.WriteLine("検証失敗"); }
ここからは、上記のコードの説明をします。なお、RSACryptoServiceProviderクラスについて詳しくは「公開鍵暗号方法で暗号化する」で説明していますので、参考にしてください(CreateKeysメソッドはそちらで紹介しているメソッドをそのまま使っています)。
CreateDigitalSignatureメソッドでは、署名を作成しています。デジタル署名を作成する手順は以下の通りです。
上記のVerifyDigitalSignatureメソッドでは、デジタル署名の検証(正当か、不当か調べる)を行っています。デジタル署名を検証する手順は、次のようになります。
RSACryptoServiceProviderクラスの代わりにDSACryptoServiceProviderクラスを使用する場合は、RSAPKCS1SignatureFormatterクラスの代わりにDSASignatureFormatterクラスを、RSAPKCS1SignatureDeformatterクラスの代わりにDSASignatureDeformatterクラスを使用します。それ以外は、同じです。
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。