Last active
July 26, 2019 05:12
-
-
Save Nia-TN1012/9500ec89d9bf4714fb5ac765fa330f36 to your computer and use it in GitHub Desktop.
.NETのICryptoTransformインターフェースの実装サンプル(シーザー暗号を例に実装)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Security.Cryptography; | |
using System.Text; | |
namespace CryptTest { | |
// ICryptoTransformインターフェースの実装サンプル | |
/// <summary> | |
/// シーザー暗号の暗号器 | |
/// </summary> | |
public class CaesarEncryptor : ICryptoTransform { | |
/// <summary> | |
/// 実装したICryptoTransformのインスタンスを使い回すことができるかどうか | |
/// </summary> | |
bool ICryptoTransform.CanReuseTransform => true; | |
bool ICryptoTransform.CanTransformMultipleBlocks => true; | |
/// <summary> | |
/// 平文のブロックサイズ | |
/// </summary> | |
int ICryptoTransform.InputBlockSize => sizeof( byte ); | |
/// <summary> | |
/// 暗号文のブロックサイズ | |
/// </summary> | |
int ICryptoTransform.OutputBlockSize => sizeof( byte ); | |
void IDisposable.Dispose() {} | |
/// <summary> | |
/// 暗号化 | |
/// </summary> | |
/// <param name="inputBuffer">平文(バイト配列)</param> | |
/// <param name="inputOffset">平文のオフセット</param> | |
/// <param name="inputCount">平文のバイト数</param> | |
/// <param name="outputBuffer">暗号文(バイト配列)</param> | |
/// <param name="outputOffset">暗号文のオフセット</param> | |
/// <returns>暗号文のバイト数</returns> | |
/// <remarks> | |
/// CryptStream経由で呼び出した場合、このメソッドで暗号化処理を行います。 | |
/// </remarks> | |
int ICryptoTransform.TransformBlock( byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset ) { | |
int writtenCount = 0; | |
for( int i = 0; i < inputCount; i++, writtenCount++ ) { | |
outputBuffer[outputOffset + i] = Encrypt( inputBuffer[inputOffset + i] ); | |
} | |
return writtenCount; | |
} | |
/// <summary> | |
/// 暗号化 | |
/// </summary> | |
/// <param name="inputBuffer">平文(バイト配列)</param> | |
/// <param name="inputOffset">平文のオフセット</param> | |
/// <param name="inputCount">平文のバイト数</param> | |
/// <returns>暗号文(バイト配列)</returns> | |
/// <remarks> | |
/// CryptStream経由で呼び出した場合、TransformBlockメソッド後に呼び出されますが、 | |
/// inputBufferには、終端コード(\0)しか入っていません。 | |
/// </remarks> | |
byte[] ICryptoTransform.TransformFinalBlock( byte[] inputBuffer, int inputOffset, int inputCount ) { | |
byte[] outputBuffer = new byte[inputCount]; | |
for( int i = 0; i < outputBuffer.Length; i++ ) { | |
outputBuffer[i] = Encrypt( inputBuffer[inputOffset + i] ); | |
} | |
return outputBuffer; | |
} | |
/// <summary> | |
/// シーザー暗号で暗号化 | |
/// </summary> | |
/// <param name="plainByte">平文</param> | |
/// <returns>暗号文</returns> | |
private byte Encrypt( byte plainByte ) => ( byte )( plainByte + 3 ); | |
} | |
/// <summary> | |
/// シーザー暗号の復号器 | |
/// </summary> | |
public class CaesarDecryptor : ICryptoTransform { | |
bool ICryptoTransform.CanReuseTransform => true; | |
bool ICryptoTransform.CanTransformMultipleBlocks => true; | |
/// <summary> | |
/// 暗号文のブロックサイズ | |
/// </summary> | |
int ICryptoTransform.InputBlockSize => sizeof( byte ); | |
/// <summary> | |
/// 平文のブロックサイズ | |
/// </summary> | |
int ICryptoTransform.OutputBlockSize => sizeof( byte ); | |
void IDisposable.Dispose() { } | |
/// <summary> | |
/// 復号 | |
/// </summary> | |
/// <param name="inputBuffer">暗号文(バイト配列)</param> | |
/// <param name="inputOffset">暗号文のオフセット</param> | |
/// <param name="inputCount">暗号文のバイト数</param> | |
/// <param name="outputBuffer">平文(バイト配列)</param> | |
/// <param name="outputOffset">平文のオフセット</param> | |
/// <returns>平文のバイト数</returns> | |
/// <remarks> | |
/// CryptStream経由で呼び出した場合、このメソッドで復号処理を行います。 | |
/// </remarks> | |
int ICryptoTransform.TransformBlock( byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset ) { | |
int writtenCount = 0; | |
for( int i = 0; i < inputCount; i++, writtenCount++ ) { | |
outputBuffer[outputOffset + i] = Decrypt( inputBuffer[inputOffset + i] ); | |
} | |
return writtenCount; | |
} | |
/// <summary> | |
/// 復号 | |
/// </summary> | |
/// <param name="inputBuffer">暗号文(バイト配列)</param> | |
/// <param name="inputOffset">暗号文のオフセット</param> | |
/// <param name="inputCount">暗号文のバイト数</param> | |
/// <returns>暗号文(バイト配列)</returns> | |
/// <remarks> | |
/// CryptStream経由で呼び出した場合、TransformBlockメソッド後に呼び出されますが、 | |
/// inputBufferには、終端コード(\0)しか入っていません。 | |
/// </remarks> | |
byte[] ICryptoTransform.TransformFinalBlock( byte[] inputBuffer, int inputOffset, int inputCount ) { | |
byte[] outputBuffer = new byte[inputCount]; | |
for( int i = 0; i < outputBuffer.Length; i++ ) { | |
outputBuffer[i] = Decrypt( inputBuffer[inputOffset + i] ); | |
} | |
return outputBuffer; | |
} | |
/// <summary> | |
/// シーザー暗号で復号 | |
/// </summary> | |
/// <param name="encByte">暗号文</param> | |
/// <returns>平文</returns> | |
private byte Decrypt( byte encByte ) => ( byte )( encByte - 3 ); | |
} | |
/// <summary> | |
/// CaesarEncryptorとCaesarDecryptorをCryptoStreamで使用して、シーザー暗号・復号を行うプログラム | |
/// </summary> | |
public static class CaesarTest { | |
public static void Test( string plain ) { | |
Console.WriteLine( $"Plain : {plain}" ); | |
// 暗号化 | |
byte[] encrypt() { | |
using( var ems = new MemoryStream() ) | |
using( var ecms = new CryptoStream( ems, new CaesarEncryptor(), CryptoStreamMode.Write ) ) | |
using( var ecmsw = new StreamWriter( ecms ) ) { | |
ecmsw.Write( plain ); | |
ecmsw.Flush(); | |
return ems.ToArray(); | |
} | |
} | |
var encByte = encrypt(); | |
var enc = Encoding.Default.GetString( encByte ); | |
Console.WriteLine( $"Encrypted: {enc}" ); | |
// 復号 | |
string decrypt() { | |
using( var dms = new MemoryStream( encByte ) ) | |
using( var dcms = new CryptoStream( dms, new CaesarDecryptor(), CryptoStreamMode.Read ) ) | |
using( var dcmsr = new StreamReader( dcms ) ) { | |
return dcmsr.ReadToEnd(); | |
} | |
} | |
var dec = decrypt(); | |
Console.WriteLine( $"Decrypted: {dec}" ); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment