Skip to content

Instantly share code, notes, and snippets.

@Nia-TN1012
Last active July 26, 2019 05:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nia-TN1012/9500ec89d9bf4714fb5ac765fa330f36 to your computer and use it in GitHub Desktop.
Save Nia-TN1012/9500ec89d9bf4714fb5ac765fa330f36 to your computer and use it in GitHub Desktop.
.NETのICryptoTransformインターフェースの実装サンプル(シーザー暗号を例に実装)
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