なぜかいきなりCamelliaをC#で実装してみました。
はてなダイアリー側に検索にきていた人がいたので何となくで実装してみました。
C#をまともに使うのはこれで2度目ですが、いろいろと言語の仕様に難儀しました。
というわけであっさりとソース
using System; using System.IO; using System.Runtime.InteropServices; namespace camellia_cs { class Camellia { public const uint CAMELLIA_HIGHPART = 1; public const uint CAMELLIA_LOWPART = 0; public const uint CAMELLIA_U8_0 = 7; public const uint CAMELLIA_U8_1 = 6; public const uint CAMELLIA_U8_2 = 5; public const uint CAMELLIA_U8_3 = 4; public const uint CAMELLIA_U8_4 = 3; public const uint CAMELLIA_U8_5 = 2; public const uint CAMELLIA_U8_6 = 1; public const uint CAMELLIA_U8_7 = 0; public const ulong CAMELLIA_SIGMA1 = 0xa09e667f3bcc908b; public const ulong CAMELLIA_SIGMA2 = 0xb67ae8584caa73b2; public const ulong CAMELLIA_SIGMA3 = 0xc6ef372fe94f82be; public const ulong CAMELLIA_SIGMA4 = 0x54ff53a5f1d36f1c; public const ulong CAMELLIA_SIGMA5 = 0x10e527fade682d1d; public const ulong CAMELLIA_SIGMA6 = 0xb05688c2b3e6c1fd; public Camellia() { m_ekey = new CamelliaKey(); m_dkey = new CamelliaKey(); m_fnCipher = Cipher128bitkey; InitializeTable(); } ~Camellia() { } unsafe public bool SetEncryptKey(MemoryStream key) { _uint128union kl,kr,ka,kb,kt1,kt2; _uint64union d1,d2,sigma; _uint64union[] k,kw,ke; switch (key.Length) { case 16: readuint128(ref kl, key); m_fnCipher = Cipher128bitkey; break; case 24: readuint128(ref kl, key); key.Seek(-8, System.IO.SeekOrigin.Current); readuint128(ref kr, key); kr.u64[CAMELLIA_HIGHPART] = kr.u64[CAMELLIA_LOWPART]; kr.u64[CAMELLIA_LOWPART] = ~kr.u64[CAMELLIA_LOWPART]; m_fnCipher = Cipher256bitkey; break; case 32: readuint128(ref kl, key); readuint128(ref kr, key); m_fnCipher = Cipher256bitkey; break; default: return false; } d1.u64 = kl.u64[CAMELLIA_HIGHPART] ^ kr.u64[CAMELLIA_HIGHPART]; d2.u64 = kl.u64[CAMELLIA_LOWPART] ^ kr.u64[CAMELLIA_LOWPART]; sigma.u64 = CAMELLIA_SIGMA1; d2.u64 ^= FFunc(d1, sigma); sigma.u64 = CAMELLIA_SIGMA2; d1.u64 ^= FFunc(d2, sigma); d1.u64 ^= kl.u64[CAMELLIA_HIGHPART]; d2.u64 ^= kl.u64[CAMELLIA_LOWPART]; sigma.u64 = CAMELLIA_SIGMA3; d2.u64 ^= FFunc(d1, sigma); sigma.u64 = CAMELLIA_SIGMA4; d1.u64 ^= FFunc(d2, sigma); ka.u64[CAMELLIA_HIGHPART] = d1.u64; ka.u64[CAMELLIA_LOWPART] = d2.u64; k = m_ekey.k; kw = m_ekey.kw; ke = m_ekey.ke; if (key.Length == 16) { kw[0].u64 = kl.u64[CAMELLIA_HIGHPART]; kw[1].u64 = kl.u64[CAMELLIA_LOWPART]; k[0].u64 = ka.u64[CAMELLIA_HIGHPART]; k[1].u64 = ka.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 15); kt2 = RotateLeft(ka, 15); k[2].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[3].u64 = kt1.u64[CAMELLIA_LOWPART]; k[4].u64 = kt2.u64[CAMELLIA_HIGHPART]; k[5].u64 = kt2.u64[CAMELLIA_LOWPART]; kt2 = RotateLeft(ka, 30); ke[0].u64 = kt2.u64[CAMELLIA_HIGHPART]; ke[1].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 45); kt2 = RotateLeft(ka, 45); k[6].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[7].u64 = kt1.u64[CAMELLIA_LOWPART]; k[8].u64 = kt2.u64[CAMELLIA_HIGHPART]; kt1 = RotateLeft(kl, 60); kt2 = RotateLeft(ka, 60); k[9].u64 = kt1.u64[CAMELLIA_LOWPART]; k[10].u64 = kt2.u64[CAMELLIA_HIGHPART]; k[11].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 77); ke[2].u64 = kt1.u64[CAMELLIA_HIGHPART]; ke[3].u64 = kt1.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 94); kt2 = RotateLeft(ka, 94); k[12].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[13].u64 = kt1.u64[CAMELLIA_LOWPART]; k[14].u64 = kt2.u64[CAMELLIA_HIGHPART]; k[15].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 111); kt2 = RotateLeft(ka, 111); k[16].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[17].u64 = kt1.u64[CAMELLIA_LOWPART]; kw[2].u64 = kt2.u64[CAMELLIA_HIGHPART]; kw[3].u64 = kt2.u64[CAMELLIA_LOWPART]; } else { d1.u64 = ka.u64[CAMELLIA_HIGHPART] ^ kr.u64[CAMELLIA_HIGHPART]; d2.u64 = ka.u64[CAMELLIA_LOWPART] ^ kr.u64[CAMELLIA_LOWPART]; sigma.u64 = CAMELLIA_SIGMA5; d2.u64 ^= FFunc(d1, sigma); sigma.u64 = CAMELLIA_SIGMA6; d1.u64 ^= FFunc(d2, sigma); kb.u64[CAMELLIA_HIGHPART] = d1.u64; kb.u64[CAMELLIA_LOWPART] = d2.u64; kw[0].u64 = kl.u64[CAMELLIA_HIGHPART]; kw[1].u64 = kl.u64[CAMELLIA_LOWPART]; k[0].u64 = kb.u64[CAMELLIA_HIGHPART]; k[1].u64 = kb.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kr, 15); kt2 = RotateLeft(ka, 15); k[2].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[3].u64 = kt1.u64[CAMELLIA_LOWPART]; k[4].u64 = kt2.u64[CAMELLIA_HIGHPART]; k[5].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kr, 30); kt2 = RotateLeft(kb, 30); ke[0].u64 = kt1.u64[CAMELLIA_HIGHPART]; ke[1].u64 = kt1.u64[CAMELLIA_LOWPART]; k[6].u64 = kt2.u64[CAMELLIA_HIGHPART]; k[7].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 45); kt2 = RotateLeft(ka, 45); k[8].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[9].u64 = kt1.u64[CAMELLIA_LOWPART]; k[10].u64 = kt2.u64[CAMELLIA_HIGHPART]; k[11].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 60); ke[2].u64 = kt1.u64[CAMELLIA_HIGHPART]; ke[3].u64 = kt1.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kr, 60); kt2 = RotateLeft(kb, 60); k[12].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[13].u64 = kt1.u64[CAMELLIA_LOWPART]; k[14].u64 = kt2.u64[CAMELLIA_HIGHPART]; k[15].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 77); kt2 = RotateLeft(ka, 77); k[16].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[17].u64 = kt1.u64[CAMELLIA_LOWPART]; ke[4].u64 = kt2.u64[CAMELLIA_HIGHPART]; ke[5].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kr, 94); kt2 = RotateLeft(ka, 94); k[18].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[19].u64 = kt1.u64[CAMELLIA_LOWPART]; k[20].u64 = kt2.u64[CAMELLIA_HIGHPART]; k[21].u64 = kt2.u64[CAMELLIA_LOWPART]; kt1 = RotateLeft(kl, 111); kt2 = RotateLeft(kb, 111); k[22].u64 = kt1.u64[CAMELLIA_HIGHPART]; k[23].u64 = kt1.u64[CAMELLIA_LOWPART]; kw[2].u64 = kt2.u64[CAMELLIA_HIGHPART]; kw[3].u64 = kt2.u64[CAMELLIA_LOWPART]; } m_dkey = (CamelliaKey)m_ekey.Clone(); ConvertDecryptKey(); return true; } public uint GetBlockSize() { return 16; } public bool Encrypt(MemoryStream outblock, MemoryStream inblock, uint blocks) { _uint128union din,dout; for(;blocks > 0;blocks--){ readuint128(ref din,inblock); m_fnCipher(ref dout,din,m_ekey); writeuint128(outblock,dout); } return true; } public bool Decrypt(MemoryStream outblock, MemoryStream inblock, uint blocks) { _uint128union din,dout; for(;blocks > 0;blocks--){ readuint128(ref din,inblock); m_fnCipher(ref dout,din,m_dkey); writeuint128(outblock,dout); } return true; } [StructLayout(LayoutKind.Explicit)] unsafe struct _uint64union{ [FieldOffset(0)] public fixed byte u8[8]; [FieldOffset(0)] public fixed uint u32[2]; [FieldOffset(0)] public ulong u64; }; [StructLayout(LayoutKind.Explicit)] unsafe struct _uint128union { [FieldOffset(0)] public fixed byte u8[16]; [FieldOffset(0)] public fixed uint u32[4]; [FieldOffset(0)] public fixed ulong u64[2]; }; class CamelliaKey : ICloneable { public CamelliaKey() { k = new _uint64union[24]; kw = new _uint64union[4]; ke = new _uint64union[6]; } protected CamelliaKey(CamelliaKey that) { this.k = (_uint64union[])that.k.Clone(); this.kw = (_uint64union[])that.kw.Clone(); this.ke = (_uint64union[])that.ke.Clone(); } public virtual object Clone() { return new CamelliaKey(this); } public _uint64union[] k; public _uint64union[] kw; public _uint64union[] ke; }; delegate void CipherMethod(ref _uint128union outblock, _uint128union inblock, CamelliaKey key); unsafe void Cipher128bitkey(ref _uint128union outblock, _uint128union inblock, CamelliaKey key) { _uint64union D1, D2; _uint64union[] k, kw, ke; k = key.k; kw = key.kw; ke = key.ke; D1.u64 = inblock.u64[CAMELLIA_HIGHPART] ^ kw[0].u64; D2.u64 = inblock.u64[CAMELLIA_LOWPART] ^ kw[1].u64; D2.u64 ^= FFunc(D1,k[0]); D1.u64 ^= FFunc(D2,k[1]); D2.u64 ^= FFunc(D1,k[2]); D1.u64 ^= FFunc(D2,k[3]); D2.u64 ^= FFunc(D1,k[4]); D1.u64 ^= FFunc(D2,k[5]); D1.u64 = FLFunc(D1,ke[0]); D2.u64 = FLInvFunc(D2,ke[1]); D2.u64 ^= FFunc(D1,k[6]); D1.u64 ^= FFunc(D2,k[7]); D2.u64 ^= FFunc(D1,k[8]); D1.u64 ^= FFunc(D2,k[9]); D2.u64 ^= FFunc(D1,k[10]); D1.u64 ^= FFunc(D2,k[11]); D1.u64 = FLFunc(D1,ke[2]); D2.u64 = FLInvFunc(D2,ke[3]); D2.u64 ^= FFunc(D1,k[12]); D1.u64 ^= FFunc(D2,k[13]); D2.u64 ^= FFunc(D1,k[14]); D1.u64 ^= FFunc(D2,k[15]); D2.u64 ^= FFunc(D1,k[16]); D1.u64 ^= FFunc(D2,k[17]); fixed (_uint128union* p = &outblock) { p->u64[CAMELLIA_HIGHPART] = D2.u64 ^ kw[2].u64; p->u64[CAMELLIA_LOWPART] = D1.u64 ^ kw[3].u64; } } unsafe void Cipher256bitkey(ref _uint128union outblock, _uint128union inblock, CamelliaKey key) { _uint64union D1, D2; _uint64union[] k, kw, ke; k = key.k; kw = key.kw; ke = key.ke; D1.u64 = inblock.u64[CAMELLIA_HIGHPART] ^kw[0].u64; D2.u64 = inblock.u64[CAMELLIA_LOWPART] ^kw[1].u64; D2.u64 ^= FFunc(D1,k[0]); D1.u64 ^= FFunc(D2,k[1]); D2.u64 ^= FFunc(D1,k[2]); D1.u64 ^= FFunc(D2,k[3]); D2.u64 ^= FFunc(D1,k[4]); D1.u64 ^= FFunc(D2,k[5]); D1.u64 = FLFunc(D1,ke[0]); D2.u64 = FLInvFunc(D2,ke[1]); D2.u64 ^= FFunc(D1,k[6]); D1.u64 ^= FFunc(D2,k[7]); D2.u64 ^= FFunc(D1,k[8]); D1.u64 ^= FFunc(D2,k[9]); D2.u64 ^= FFunc(D1,k[10]); D1.u64 ^= FFunc(D2,k[11]); D1.u64 = FLFunc(D1,ke[2]); D2.u64 = FLInvFunc(D2,ke[3]); D2.u64 ^= FFunc(D1,k[12]); D1.u64 ^= FFunc(D2,k[13]); D2.u64 ^= FFunc(D1,k[14]); D1.u64 ^= FFunc(D2,k[15]); D2.u64 ^= FFunc(D1,k[16]); D1.u64 ^= FFunc(D2,k[17]); D1.u64 = FLFunc(D1,ke[4]); D2.u64 = FLInvFunc(D2,ke[5]); D2.u64 ^= FFunc(D1,k[18]); D1.u64 ^= FFunc(D2,k[19]); D2.u64 ^= FFunc(D1,k[20]); D1.u64 ^= FFunc(D2,k[21]); D2.u64 ^= FFunc(D1,k[22]); D1.u64 ^= FFunc(D2,k[23]); fixed (_uint128union* p = &outblock) { p->u64[CAMELLIA_HIGHPART] = D2.u64 ^kw[2].u64; p->u64[CAMELLIA_LOWPART] = D1.u64 ^kw[3].u64; } } void ConvertDecryptKey() { swapuint64(ref m_dkey.kw[0], ref m_dkey.kw[2]); swapuint64(ref m_dkey.kw[1], ref m_dkey.kw[3]); if(m_fnCipher == Cipher128bitkey){ swapuint64(ref m_dkey.ke[0], ref m_dkey.ke[3]); swapuint64(ref m_dkey.ke[1], ref m_dkey.ke[2]); for(uint i = 0;i <= 8;i++){ swapuint64(ref m_dkey.k[i], ref m_dkey.k[17 - i]); } } else{ swapuint64(ref m_dkey.ke[0], ref m_dkey.ke[5]); swapuint64(ref m_dkey.ke[1], ref m_dkey.ke[4]); swapuint64(ref m_dkey.ke[2], ref m_dkey.ke[3]); for(uint i = 0;i <= 11;i++){ swapuint64(ref m_dkey.k[i], ref m_dkey.k[23 - i]); } } } static void InitializeTable() { uint c1, c2, c3, c4; if (m_initsbox) return; m_aaiSBox = new uint[4, 256]; for (uint i = 0; i < 256; i++) { c1 = m_aiSBoxBase[i]; c2 = RotateLeft(m_aiSBoxBase[i], 1); c3 = RotateLeft(m_aiSBoxBase[i], 7); c4 = m_aiSBoxBase[RotateLeft((byte)i, 1)]; m_aaiSBox[0,i] = (c1 << 24) | (c1 << 16) | (c1 << 8); m_aaiSBox[1,i] = (c2 << 16) | (c2 << 8) | c2; m_aaiSBox[2,i] = (c3 << 24) | (c3 << 8) | c3; m_aaiSBox[3,i] = (c4 << 24) | (c4 << 16) | c4; } m_initsbox = true; } unsafe static ulong FFunc(_uint64union fin, _uint64union ke) { uint[] t = new uint[8]; uint n; _uint64union x; x.u64 = fin.u64 ^ ke.u64; t[0] = m_aaiSBox[0,x.u8[CAMELLIA_U8_0]]; t[1] = m_aaiSBox[1,x.u8[CAMELLIA_U8_1]]; t[2] = m_aaiSBox[2,x.u8[CAMELLIA_U8_2]]; t[3] = m_aaiSBox[3,x.u8[CAMELLIA_U8_3]]; t[4] = m_aaiSBox[1,x.u8[CAMELLIA_U8_4]]; t[5] = m_aaiSBox[2,x.u8[CAMELLIA_U8_5]]; t[6] = m_aaiSBox[3,x.u8[CAMELLIA_U8_6]]; t[7] = m_aaiSBox[0,x.u8[CAMELLIA_U8_7]]; n = t[4] ^ t[5] ^ t[6] ^ t[7]; x.u32[CAMELLIA_HIGHPART] = t[0] ^ t[1] ^ t[2] ^ t[3] ^ n; x.u32[CAMELLIA_LOWPART] = RotateLeft(t[0] & 0xffff0000,8) ^ ((t[1] & 0x00ffff00) << 8) ^ ((t[2] & 0x0000ffff) << 8) ^ RotateLeft(t[3] & 0xff0000ff,8) ^ n; return x.u64; } unsafe static ulong FLFunc(_uint64union fin, _uint64union ke) { _uint64union val; val.u64 = 0; val.u32[CAMELLIA_LOWPART] = fin.u32[CAMELLIA_LOWPART] ^ RotateLeft(fin.u32[CAMELLIA_HIGHPART] & ke.u32[CAMELLIA_HIGHPART], 1); val.u32[CAMELLIA_HIGHPART] = fin.u32[CAMELLIA_HIGHPART] ^ (val.u32[CAMELLIA_LOWPART] | ke.u32[CAMELLIA_LOWPART]); return val.u64; } unsafe static ulong FLInvFunc(_uint64union fin, _uint64union ke) { _uint64union val; val.u64 = 0; val.u32[CAMELLIA_HIGHPART] = fin.u32[CAMELLIA_HIGHPART] ^ (fin.u32[CAMELLIA_LOWPART] | ke.u32[CAMELLIA_LOWPART]); val.u32[CAMELLIA_LOWPART] = fin.u32[CAMELLIA_LOWPART] ^ RotateLeft(val.u32[CAMELLIA_HIGHPART] & ke.u32[CAMELLIA_HIGHPART], 1); return val.u64; } static byte RotateLeft(byte val, int shift) { return (byte)((((uint)val | ((uint)val << 8)) << shift) >> 8); } static uint RotateLeft(uint val, int shift) { return (val << shift) | (val >> (32 - shift)); } static ulong RotateLeft(_uint64union val, int shift) { return (val.u64 << shift) | (val.u64 >> (64 - shift)); } unsafe static _uint128union RotateLeft(_uint128union val, int shift) { _uint128union ret; if (shift == 0) { ret = val; } else if (shift == 64) { ret.u64[0] = val.u64[1]; ret.u64[1] = val.u64[0]; } else if (shift < 64) { ret.u64[CAMELLIA_LOWPART] = (val.u64[CAMELLIA_LOWPART] << shift) | (val.u64[CAMELLIA_HIGHPART] >> (64 - shift)); ret.u64[CAMELLIA_HIGHPART] = (val.u64[CAMELLIA_HIGHPART] << shift) | (val.u64[CAMELLIA_LOWPART] >> (64 - shift)); } else { shift = 128 - shift; ret.u64[CAMELLIA_LOWPART] = (val.u64[CAMELLIA_LOWPART] >> shift) | (val.u64[CAMELLIA_HIGHPART] << (64 - shift)); ret.u64[CAMELLIA_HIGHPART] = (val.u64[CAMELLIA_HIGHPART] >> shift) | (val.u64[CAMELLIA_LOWPART] << (64 - shift)); } return ret; } static void swapuint64(ref _uint64union x, ref _uint64union y) { ulong n = x.u64; x.u64 = y.u64; y.u64 = n; } unsafe static void readuint128(ref _uint128union dest, MemoryStream src) { int n; fixed (_uint128union* p = &dest) { for (int i = 0; i < 16; i++) { n = src.ReadByte(); p->u8[15 - i] = (byte)(n >= 0 ? n : 0); } } } unsafe static void writeuint128(MemoryStream dest, _uint128union src) { for (int i = 0; i < 16; i++) { dest.WriteByte(src.u8[15 - i]); } } static bool m_initsbox; static uint[,] m_aaiSBox; static byte[] m_aiSBoxBase = new byte[] { 0x70, 0x82, 0x2c, 0xec, 0xb3, 0x27, 0xc0, 0xe5, 0xe4, 0x85, 0x57, 0x35, 0xea, 0x0c, 0xae, 0x41, 0x23, 0xef, 0x6b, 0x93, 0x45, 0x19, 0xa5, 0x21, 0xed, 0x0e, 0x4f, 0x4e, 0x1d, 0x65, 0x92, 0xbd, 0x86, 0xb8, 0xaf, 0x8f, 0x7c, 0xeb, 0x1f, 0xce, 0x3e, 0x30, 0xdc, 0x5f, 0x5e, 0xc5, 0x0b, 0x1a, 0xa6, 0xe1, 0x39, 0xca, 0xd5, 0x47, 0x5d, 0x3d, 0xd9, 0x01, 0x5a, 0xd6, 0x51, 0x56, 0x6c, 0x4d, 0x8b, 0x0d, 0x9a, 0x66, 0xfb, 0xcc, 0xb0, 0x2d, 0x74, 0x12, 0x2b, 0x20, 0xf0, 0xb1, 0x84, 0x99, 0xdf, 0x4c, 0xcb, 0xc2, 0x34, 0x7e, 0x76, 0x05, 0x6d, 0xb7, 0xa9, 0x31, 0xd1, 0x17, 0x04, 0xd7, 0x14, 0x58, 0x3a, 0x61, 0xde, 0x1b, 0x11, 0x1c, 0x32, 0x0f, 0x9c, 0x16, 0x53, 0x18, 0xf2, 0x22, 0xfe, 0x44, 0xcf, 0xb2, 0xc3, 0xb5, 0x7a, 0x91, 0x24, 0x08, 0xe8, 0xa8, 0x60, 0xfc, 0x69, 0x50, 0xaa, 0xd0, 0xa0, 0x7d, 0xa1, 0x89, 0x62, 0x97, 0x54, 0x5b, 0x1e, 0x95, 0xe0, 0xff, 0x64, 0xd2, 0x10, 0xc4, 0x00, 0x48, 0xa3, 0xf7, 0x75, 0xdb, 0x8a, 0x03, 0xe6, 0xda, 0x09, 0x3f, 0xdd, 0x94, 0x87, 0x5c, 0x83, 0x02, 0xcd, 0x4a, 0x90, 0x33, 0x73, 0x67, 0xf6, 0xf3, 0x9d, 0x7f, 0xbf, 0xe2, 0x52, 0x9b, 0xd8, 0x26, 0xc8, 0x37, 0xc6, 0x3b, 0x81, 0x96, 0x6f, 0x4b, 0x13, 0xbe, 0x63, 0x2e, 0xe9, 0x79, 0xa7, 0x8c, 0x9f, 0x6e, 0xbc, 0x8e, 0x29, 0xf5, 0xf9, 0xb6, 0x2f, 0xfd, 0xb4, 0x59, 0x78, 0x98, 0x06, 0x6a, 0xe7, 0x46, 0x71, 0xba, 0xd4, 0x25, 0xab, 0x42, 0x88, 0xa2, 0x8d, 0xfa, 0x72, 0x07, 0xb9, 0x55, 0xf8, 0xee, 0xac, 0x0a, 0x36, 0x49, 0x2a, 0x68, 0x3c, 0x38, 0xf1, 0xa4, 0x40, 0x28, 0xd3, 0x7b, 0xbb, 0xc9, 0x43, 0xc1, 0x15, 0xe3, 0xad, 0xf4, 0x77, 0xc7, 0x80, 0x9e }; CamelliaKey m_ekey, m_dkey; CipherMethod m_fnCipher; } }
元々がC++のコードなので
それを素直に変換しただけです。
面倒だったのはC#では基本的に共用体を扱えない、というところですね。
言語的に考えれば当たり前なのですが、それを「当たり前」で済ませるわけにも行かないのでなんとか共用体を宣言できる形に持って行きました。
おかげでunsafeコードの山となってしまいました・・・。C#なのでこれは余り良くないですね。
共用体を使わずにやるなら共用体もどきクラスを作って各データの取得要求のたびに変換して渡す、とかですか。
後、暗号処理対象のデータはMemoryStream経由で渡します。たぶんMemoryStreamでなくても同じメンバを持っていればいいような気はしますのでもしこのコードを参考にするなら使いやすいものに変えてもいいと思います。
ADVシステムに関するWikiページを構築中・・・
前にも言っていましたが、Wikiページを作って情報を集めてみようかと思います。
WindowModePatchの対応情報ページも含めたものになる予定です。
しかし、はじめてWikiを扱いましたが、文法がまだわからないので手間取っています。
編集履歴でいろいろと不自然なものが大量にできあがる、という問題もあったり。
公開できるまでにはまだまだ時間がかかりそうです。