www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - blowfish

reply r <r_member pathlink.com> writes:
i use and it seems to work, not very well tested so. i hope i interpreted the
license correctly.

r

/*
The Bouncy Castle License
Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
(http://www.bouncycastle.org)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software 
and associated documentation files (the "Software"), to deal in the Software
without restriction, 
including without limitation the rights to use, copy, modify, merge, publish,
distribute, sub license, 
and/or sell copies of the Software, and to permit persons to whom the Software
is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER
DEALINGS IN THE SOFTWARE.
*/

import std.stdio;
import std.string;

/**
* A class that provides Blowfish key encryption operations,
* such as encoding data and generating keys.
* All the algorithms herein are from Applied Cryptography
* and implement a simplified cryptography interface.
*/
public class BlowfishEngine
{
private const int[]
KP = [
cast(int) 0x243F6A88, cast(int) 0x85A308D3, cast(int) 0x13198A2E, cast(int)
0x03707344,
cast(int) 0xA4093822, cast(int) 0x299F31D0, cast(int) 0x082EFA98, cast(int)
0xEC4E6C89,
cast(int) 0x452821E6, cast(int) 0x38D01377, cast(int) 0xBE5466CF, cast(int)
0x34E90C6C,
cast(int) 0xC0AC29B7, cast(int) 0xC97C50DD, cast(int) 0x3F84D5B5, cast(int)
0xB5470917,
cast(int) 0x9216D5D9, cast(int) 0x8979FB1B
];

private const int[]
KS0 = [
cast(int) 0xD1310BA6, cast(int) 0x98DFB5AC, cast(int) 0x2FFD72DB, cast(int)
0xD01ADFB7,
cast(int) 0xB8E1AFED, cast(int) 0x6A267E96, cast(int) 0xBA7C9045, cast(int)
0xF12C7F99,
cast(int) 0x24A19947, cast(int) 0xB3916CF7, cast(int) 0x0801F2E2, cast(int)
0x858EFC16,
cast(int) 0x636920D8, cast(int) 0x71574E69, cast(int) 0xA458FEA3, cast(int)
0xF4933D7E,
cast(int) 0x0D95748F, cast(int) 0x728EB658, cast(int) 0x718BCD58, cast(int)
0x82154AEE,
cast(int) 0x7B54A41D, cast(int) 0xC25A59B5, cast(int) 0x9C30D539, cast(int)
0x2AF26013,
cast(int) 0xC5D1B023, cast(int) 0x286085F0, cast(int) 0xCA417918, cast(int)
0xB8DB38EF,
cast(int) 0x8E79DCB0, cast(int) 0x603A180E, cast(int) 0x6C9E0E8B, cast(int)
0xB01E8A3E,
cast(int) 0xD71577C1, cast(int) 0xBD314B27, cast(int) 0x78AF2FDA, cast(int)
0x55605C60,
cast(int) 0xE65525F3, cast(int) 0xAA55AB94, cast(int) 0x57489862, cast(int)
0x63E81440,
cast(int) 0x55CA396A, cast(int) 0x2AAB10B6, cast(int) 0xB4CC5C34, cast(int)
0x1141E8CE,
cast(int) 0xA15486AF, cast(int) 0x7C72E993, cast(int) 0xB3EE1411, cast(int)
0x636FBC2A,
cast(int) 0x2BA9C55D, cast(int) 0x741831F6, cast(int) 0xCE5C3E16, cast(int)
0x9B87931E,
cast(int) 0xAFD6BA33, cast(int) 0x6C24CF5C, cast(int) 0x7A325381, cast(int)
0x28958677,
cast(int) 0x3B8F4898, cast(int) 0x6B4BB9AF, cast(int) 0xC4BFE81B, cast(int)
0x66282193,
cast(int) 0x61D809CC, cast(int) 0xFB21A991, cast(int) 0x487CAC60, cast(int)
0x5DEC8032,
cast(int) 0xEF845D5D, cast(int) 0xE98575B1, cast(int) 0xDC262302, cast(int)
0xEB651B88,
cast(int) 0x23893E81, cast(int) 0xD396ACC5, cast(int) 0x0F6D6FF3, cast(int)
0x83F44239,
cast(int) 0x2E0B4482, cast(int) 0xA4842004, cast(int) 0x69C8F04A, cast(int)
0x9E1F9B5E,
cast(int) 0x21C66842, cast(int) 0xF6E96C9A, cast(int) 0x670C9C61, cast(int)
0xABD388F0,
cast(int) 0x6A51A0D2, cast(int) 0xD8542F68, cast(int) 0x960FA728, cast(int)
0xAB5133A3,
cast(int) 0x6EEF0B6C, cast(int) 0x137A3BE4, cast(int) 0xBA3BF050, cast(int)
0x7EFB2A98,
cast(int) 0xA1F1651D, cast(int) 0x39AF0176, cast(int) 0x66CA593E, cast(int)
0x82430E88,
cast(int) 0x8CEE8619, cast(int) 0x456F9FB4, cast(int) 0x7D84A5C3, cast(int)
0x3B8B5EBE,
cast(int) 0xE06F75D8, cast(int) 0x85C12073, cast(int) 0x401A449F, cast(int)
0x56C16AA6,
cast(int) 0x4ED3AA62, cast(int) 0x363F7706, cast(int) 0x1BFEDF72, cast(int)
0x429B023D,
cast(int) 0x37D0D724, cast(int) 0xD00A1248, cast(int) 0xDB0FEAD3, cast(int)
0x49F1C09B,
cast(int) 0x075372C9, cast(int) 0x80991B7B, cast(int) 0x25D479D8, cast(int)
0xF6E8DEF7,
cast(int) 0xE3FE501A, cast(int) 0xB6794C3B, cast(int) 0x976CE0BD, cast(int)
0x04C006BA,
cast(int) 0xC1A94FB6, cast(int) 0x409F60C4, cast(int) 0x5E5C9EC2, cast(int)
0x196A2463,
cast(int) 0x68FB6FAF, cast(int) 0x3E6C53B5, cast(int) 0x1339B2EB, cast(int)
0x3B52EC6F,
cast(int) 0x6DFC511F, cast(int) 0x9B30952C, cast(int) 0xCC814544, cast(int)
0xAF5EBD09,
cast(int) 0xBEE3D004, cast(int) 0xDE334AFD, cast(int) 0x660F2807, cast(int)
0x192E4BB3,
cast(int) 0xC0CBA857, cast(int) 0x45C8740F, cast(int) 0xD20B5F39, cast(int)
0xB9D3FBDB,
cast(int) 0x5579C0BD, cast(int) 0x1A60320A, cast(int) 0xD6A100C6, cast(int)
0x402C7279,
cast(int) 0x679F25FE, cast(int) 0xFB1FA3CC, cast(int) 0x8EA5E9F8, cast(int)
0xDB3222F8,
cast(int) 0x3C7516DF, cast(int) 0xFD616B15, cast(int) 0x2F501EC8, cast(int)
0xAD0552AB,
cast(int) 0x323DB5FA, cast(int) 0xFD238760, cast(int) 0x53317B48, cast(int)
0x3E00DF82,
cast(int) 0x9E5C57BB, cast(int) 0xCA6F8CA0, cast(int) 0x1A87562E, cast(int)
0xDF1769DB,
cast(int) 0xD542A8F6, cast(int) 0x287EFFC3, cast(int) 0xAC6732C6, cast(int)
0x8C4F5573,
cast(int) 0x695B27B0, cast(int) 0xBBCA58C8, cast(int) 0xE1FFA35D, cast(int)
0xB8F011A0,
cast(int) 0x10FA3D98, cast(int) 0xFD2183B8, cast(int) 0x4AFCB56C, cast(int)
0x2DD1D35B,
cast(int) 0x9A53E479, cast(int) 0xB6F84565, cast(int) 0xD28E49BC, cast(int)
0x4BFB9790,
cast(int) 0xE1DDF2DA, cast(int) 0xA4CB7E33, cast(int) 0x62FB1341, cast(int)
0xCEE4C6E8,
cast(int) 0xEF20CADA, cast(int) 0x36774C01, cast(int) 0xD07E9EFE, cast(int)
0x2BF11FB4,
cast(int) 0x95DBDA4D, cast(int) 0xAE909198, cast(int) 0xEAAD8E71, cast(int)
0x6B93D5A0,
cast(int) 0xD08ED1D0, cast(int) 0xAFC725E0, cast(int) 0x8E3C5B2F, cast(int)
0x8E7594B7,
cast(int) 0x8FF6E2FB, cast(int) 0xF2122B64, cast(int) 0x8888B812, cast(int)
0x900DF01C,
cast(int) 0x4FAD5EA0, cast(int) 0x688FC31C, cast(int) 0xD1CFF191, cast(int)
0xB3A8C1AD,
cast(int) 0x2F2F2218, cast(int) 0xBE0E1777, cast(int) 0xEA752DFE, cast(int)
0x8B021FA1,
cast(int) 0xE5A0CC0F, cast(int) 0xB56F74E8, cast(int) 0x18ACF3D6, cast(int)
0xCE89E299,
cast(int) 0xB4A84FE0, cast(int) 0xFD13E0B7, cast(int) 0x7CC43B81, cast(int)
0xD2ADA8D9,
cast(int) 0x165FA266, cast(int) 0x80957705, cast(int) 0x93CC7314, cast(int)
0x211A1477,
cast(int) 0xE6AD2065, cast(int) 0x77B5FA86, cast(int) 0xC75442F5, cast(int)
0xFB9D35CF,
cast(int) 0xEBCDAF0C, cast(int) 0x7B3E89A0, cast(int) 0xD6411BD3, cast(int)
0xAE1E7E49,
cast(int) 0x00250E2D, cast(int) 0x2071B35E, cast(int) 0x226800BB, cast(int)
0x57B8E0AF,
cast(int) 0x2464369B, cast(int) 0xF009B91E, cast(int) 0x5563911D, cast(int)
0x59DFA6AA,
cast(int) 0x78C14389, cast(int) 0xD95A537F, cast(int) 0x207D5BA2, cast(int)
0x02E5B9C5,
cast(int) 0x83260376, cast(int) 0x6295CFA9, cast(int) 0x11C81968, cast(int)
0x4E734A41,
cast(int) 0xB3472DCA, cast(int) 0x7B14A94A, cast(int) 0x1B510052, cast(int)
0x9A532915,
cast(int) 0xD60F573F, cast(int) 0xBC9BC6E4, cast(int) 0x2B60A476, cast(int)
0x81E67400,
cast(int) 0x08BA6FB5, cast(int) 0x571BE91F, cast(int) 0xF296EC6B, cast(int)
0x2A0DD915,
cast(int) 0xB6636521, cast(int) 0xE7B9F9B6, cast(int) 0xFF34052E, cast(int)
0xC5855664,
cast(int) 0x53B02D5D, cast(int) 0xA99F8FA1, cast(int) 0x08BA4799, cast(int)
0x6E85076A
];

private const int[]
KS1 = [
cast(int) 0x4B7A70E9, cast(int) 0xB5B32944, cast(int) 0xDB75092E, cast(int)
0xC4192623,
cast(int) 0xAD6EA6B0, cast(int) 0x49A7DF7D, cast(int) 0x9CEE60B8, cast(int)
0x8FEDB266,
cast(int) 0xECAA8C71, cast(int) 0x699A17FF, cast(int) 0x5664526C, cast(int)
0xC2B19EE1,
cast(int) 0x193602A5, cast(int) 0x75094C29, cast(int) 0xA0591340, cast(int)
0xE4183A3E,
cast(int) 0x3F54989A, cast(int) 0x5B429D65, cast(int) 0x6B8FE4D6, cast(int)
0x99F73FD6,
cast(int) 0xA1D29C07, cast(int) 0xEFE830F5, cast(int) 0x4D2D38E6, cast(int)
0xF0255DC1,
cast(int) 0x4CDD2086, cast(int) 0x8470EB26, cast(int) 0x6382E9C6, cast(int)
0x021ECC5E,
cast(int) 0x09686B3F, cast(int) 0x3EBAEFC9, cast(int) 0x3C971814, cast(int)
0x6B6A70A1,
cast(int) 0x687F3584, cast(int) 0x52A0E286, cast(int) 0xB79C5305, cast(int)
0xAA500737,
cast(int) 0x3E07841C, cast(int) 0x7FDEAE5C, cast(int) 0x8E7D44EC, cast(int)
0x5716F2B8,
cast(int) 0xB03ADA37, cast(int) 0xF0500C0D, cast(int) 0xF01C1F04, cast(int)
0x0200B3FF,
cast(int) 0xAE0CF51A, cast(int) 0x3CB574B2, cast(int) 0x25837A58, cast(int)
0xDC0921BD,
cast(int) 0xD19113F9, cast(int) 0x7CA92FF6, cast(int) 0x94324773, cast(int)
0x22F54701,
cast(int) 0x3AE5E581, cast(int) 0x37C2DADC, cast(int) 0xC8B57634, cast(int)
0x9AF3DDA7,
cast(int) 0xA9446146, cast(int) 0x0FD0030E, cast(int) 0xECC8C73E, cast(int)
0xA4751E41,
cast(int) 0xE238CD99, cast(int) 0x3BEA0E2F, cast(int) 0x3280BBA1, cast(int)
0x183EB331,
cast(int) 0x4E548B38, cast(int) 0x4F6DB908, cast(int) 0x6F420D03, cast(int)
0xF60A04BF,
cast(int) 0x2CB81290, cast(int) 0x24977C79, cast(int) 0x5679B072, cast(int)
0xBCAF89AF,
cast(int) 0xDE9A771F, cast(int) 0xD9930810, cast(int) 0xB38BAE12, cast(int)
0xDCCF3F2E,
cast(int) 0x5512721F, cast(int) 0x2E6B7124, cast(int) 0x501ADDE6, cast(int)
0x9F84CD87,
cast(int) 0x7A584718, cast(int) 0x7408DA17, cast(int) 0xBC9F9ABC, cast(int)
0xE94B7D8C,
cast(int) 0xEC7AEC3A, cast(int) 0xDB851DFA, cast(int) 0x63094366, cast(int)
0xC464C3D2,
cast(int) 0xEF1C1847, cast(int) 0x3215D908, cast(int) 0xDD433B37, cast(int)
0x24C2BA16,
cast(int) 0x12A14D43, cast(int) 0x2A65C451, cast(int) 0x50940002, cast(int)
0x133AE4DD,
cast(int) 0x71DFF89E, cast(int) 0x10314E55, cast(int) 0x81AC77D6, cast(int)
0x5F11199B,
cast(int) 0x043556F1, cast(int) 0xD7A3C76B, cast(int) 0x3C11183B, cast(int)
0x5924A509,
cast(int) 0xF28FE6ED, cast(int) 0x97F1FBFA, cast(int) 0x9EBABF2C, cast(int)
0x1E153C6E,
cast(int) 0x86E34570, cast(int) 0xEAE96FB1, cast(int) 0x860E5E0A, cast(int)
0x5A3E2AB3,
cast(int) 0x771FE71C, cast(int) 0x4E3D06FA, cast(int) 0x2965DCB9, cast(int)
0x99E71D0F,
cast(int) 0x803E89D6, cast(int) 0x5266C825, cast(int) 0x2E4CC978, cast(int)
0x9C10B36A,
cast(int) 0xC6150EBA, cast(int) 0x94E2EA78, cast(int) 0xA5FC3C53, cast(int)
0x1E0A2DF4,
cast(int) 0xF2F74EA7, cast(int) 0x361D2B3D, cast(int) 0x1939260F, cast(int)
0x19C27960,
cast(int) 0x5223A708, cast(int) 0xF71312B6, cast(int) 0xEBADFE6E, cast(int)
0xEAC31F66,
cast(int) 0xE3BC4595, cast(int) 0xA67BC883, cast(int) 0xB17F37D1, cast(int)
0x018CFF28,
cast(int) 0xC332DDEF, cast(int) 0xBE6C5AA5, cast(int) 0x65582185, cast(int)
0x68AB9802,
cast(int) 0xEECEA50F, cast(int) 0xDB2F953B, cast(int) 0x2AEF7DAD, cast(int)
0x5B6E2F84,
cast(int) 0x1521B628, cast(int) 0x29076170, cast(int) 0xECDD4775, cast(int)
0x619F1510,
cast(int) 0x13CCA830, cast(int) 0xEB61BD96, cast(int) 0x0334FE1E, cast(int)
0xAA0363CF,
cast(int) 0xB5735C90, cast(int) 0x4C70A239, cast(int) 0xD59E9E0B, cast(int)
0xCBAADE14,
cast(int) 0xEECC86BC, cast(int) 0x60622CA7, cast(int) 0x9CAB5CAB, cast(int)
0xB2F3846E,
cast(int) 0x648B1EAF, cast(int) 0x19BDF0CA, cast(int) 0xA02369B9, cast(int)
0x655ABB50,
cast(int) 0x40685A32, cast(int) 0x3C2AB4B3, cast(int) 0x319EE9D5, cast(int)
0xC021B8F7,
cast(int) 0x9B540B19, cast(int) 0x875FA099, cast(int) 0x95F7997E, cast(int)
0x623D7DA8,
cast(int) 0xF837889A, cast(int) 0x97E32D77, cast(int) 0x11ED935F, cast(int)
0x16681281,
cast(int) 0x0E358829, cast(int) 0xC7E61FD6, cast(int) 0x96DEDFA1, cast(int)
0x7858BA99,
cast(int) 0x57F584A5, cast(int) 0x1B227263, cast(int) 0x9B83C3FF, cast(int)
0x1AC24696,
cast(int) 0xCDB30AEB, cast(int) 0x532E3054, cast(int) 0x8FD948E4, cast(int)
0x6DBC3128,
cast(int) 0x58EBF2EF, cast(int) 0x34C6FFEA, cast(int) 0xFE28ED61, cast(int)
0xEE7C3C73,
cast(int) 0x5D4A14D9, cast(int) 0xE864B7E3, cast(int) 0x42105D14, cast(int)
0x203E13E0,
cast(int) 0x45EEE2B6, cast(int) 0xA3AAABEA, cast(int) 0xDB6C4F15, cast(int)
0xFACB4FD0,
cast(int) 0xC742F442, cast(int) 0xEF6ABBB5, cast(int) 0x654F3B1D, cast(int)
0x41CD2105,
cast(int) 0xD81E799E, cast(int) 0x86854DC7, cast(int) 0xE44B476A, cast(int)
0x3D816250,
cast(int) 0xCF62A1F2, cast(int) 0x5B8D2646, cast(int) 0xFC8883A0, cast(int)
0xC1C7B6A3,
cast(int) 0x7F1524C3, cast(int) 0x69CB7492, cast(int) 0x47848A0B, cast(int)
0x5692B285,
cast(int) 0x095BBF00, cast(int) 0xAD19489D, cast(int) 0x1462B174, cast(int)
0x23820E00,
cast(int) 0x58428D2A, cast(int) 0x0C55F5EA, cast(int) 0x1DADF43E, cast(int)
0x233F7061,
cast(int) 0x3372F092, cast(int) 0x8D937E41, cast(int) 0xD65FECF1, cast(int)
0x6C223BDB,
cast(int) 0x7CDE3759, cast(int) 0xCBEE7460, cast(int) 0x4085F2A7, cast(int)
0xCE77326E,
cast(int) 0xA6078084, cast(int) 0x19F8509E, cast(int) 0xE8EFD855, cast(int)
0x61D99735,
cast(int) 0xA969A7AA, cast(int) 0xC50C06C2, cast(int) 0x5A04ABFC, cast(int)
0x800BCADC,
cast(int) 0x9E447A2E, cast(int) 0xC3453484, cast(int) 0xFDD56705, cast(int)
0x0E1E9EC9,
cast(int) 0xDB73DBD3, cast(int) 0x105588CD, cast(int) 0x675FDA79, cast(int)
0xE3674340,
cast(int) 0xC5C43465, cast(int) 0x713E38D8, cast(int) 0x3D28F89E, cast(int)
0xF16DFF20,
cast(int) 0x153E21E7, cast(int) 0x8FB03D4A, cast(int) 0xE6E39F2B, cast(int)
0xDB83ADF7
];

private const int[]
KS2 = [
cast(int) 0xE93D5A68, cast(int) 0x948140F7, cast(int) 0xF64C261C, cast(int)
0x94692934,
cast(int) 0x411520F7, cast(int) 0x7602D4F7, cast(int) 0xBCF46B2E, cast(int)
0xD4A20068,
cast(int) 0xD4082471, cast(int) 0x3320F46A, cast(int) 0x43B7D4B7, cast(int)
0x500061AF,
cast(int) 0x1E39F62E, cast(int) 0x97244546, cast(int) 0x14214F74, cast(int)
0xBF8B8840,
cast(int) 0x4D95FC1D, cast(int) 0x96B591AF, cast(int) 0x70F4DDD3, cast(int)
0x66A02F45,
cast(int) 0xBFBC09EC, cast(int) 0x03BD9785, cast(int) 0x7FAC6DD0, cast(int)
0x31CB8504,
cast(int) 0x96EB27B3, cast(int) 0x55FD3941, cast(int) 0xDA2547E6, cast(int)
0xABCA0A9A,
cast(int) 0x28507825, cast(int) 0x530429F4, cast(int) 0x0A2C86DA, cast(int)
0xE9B66DFB,
cast(int) 0x68DC1462, cast(int) 0xD7486900, cast(int) 0x680EC0A4, cast(int)
0x27A18DEE,
cast(int) 0x4F3FFEA2, cast(int) 0xE887AD8C, cast(int) 0xB58CE006, cast(int)
0x7AF4D6B6,
cast(int) 0xAACE1E7C, cast(int) 0xD3375FEC, cast(int) 0xCE78A399, cast(int)
0x406B2A42,
cast(int) 0x20FE9E35, cast(int) 0xD9F385B9, cast(int) 0xEE39D7AB, cast(int)
0x3B124E8B,
cast(int) 0x1DC9FAF7, cast(int) 0x4B6D1856, cast(int) 0x26A36631, cast(int)
0xEAE397B2,
cast(int) 0x3A6EFA74, cast(int) 0xDD5B4332, cast(int) 0x6841E7F7, cast(int)
0xCA7820FB,
cast(int) 0xFB0AF54E, cast(int) 0xD8FEB397, cast(int) 0x454056AC, cast(int)
0xBA489527,
cast(int) 0x55533A3A, cast(int) 0x20838D87, cast(int) 0xFE6BA9B7, cast(int)
0xD096954B,
cast(int) 0x55A867BC, cast(int) 0xA1159A58, cast(int) 0xCCA92963, cast(int)
0x99E1DB33,
cast(int) 0xA62A4A56, cast(int) 0x3F3125F9, cast(int) 0x5EF47E1C, cast(int)
0x9029317C,
cast(int) 0xFDF8E802, cast(int) 0x04272F70, cast(int) 0x80BB155C, cast(int)
0x05282CE3,
cast(int) 0x95C11548, cast(int) 0xE4C66D22, cast(int) 0x48C1133F, cast(int)
0xC70F86DC,
cast(int) 0x07F9C9EE, cast(int) 0x41041F0F, cast(int) 0x404779A4, cast(int)
0x5D886E17,
cast(int) 0x325F51EB, cast(int) 0xD59BC0D1, cast(int) 0xF2BCC18F, cast(int)
0x41113564,
cast(int) 0x257B7834, cast(int) 0x602A9C60, cast(int) 0xDFF8E8A3, cast(int)
0x1F636C1B,
cast(int) 0x0E12B4C2, cast(int) 0x02E1329E, cast(int) 0xAF664FD1, cast(int)
0xCAD18115,
cast(int) 0x6B2395E0, cast(int) 0x333E92E1, cast(int) 0x3B240B62, cast(int)
0xEEBEB922,
cast(int) 0x85B2A20E, cast(int) 0xE6BA0D99, cast(int) 0xDE720C8C, cast(int)
0x2DA2F728,
cast(int) 0xD0127845, cast(int) 0x95B794FD, cast(int) 0x647D0862, cast(int)
0xE7CCF5F0,
cast(int) 0x5449A36F, cast(int) 0x877D48FA, cast(int) 0xC39DFD27, cast(int)
0xF33E8D1E,
cast(int) 0x0A476341, cast(int) 0x992EFF74, cast(int) 0x3A6F6EAB, cast(int)
0xF4F8FD37,
cast(int) 0xA812DC60, cast(int) 0xA1EBDDF8, cast(int) 0x991BE14C, cast(int)
0xDB6E6B0D,
cast(int) 0xC67B5510, cast(int) 0x6D672C37, cast(int) 0x2765D43B, cast(int)
0xDCD0E804,
cast(int) 0xF1290DC7, cast(int) 0xCC00FFA3, cast(int) 0xB5390F92, cast(int)
0x690FED0B,
cast(int) 0x667B9FFB, cast(int) 0xCEDB7D9C, cast(int) 0xA091CF0B, cast(int)
0xD9155EA3,
cast(int) 0xBB132F88, cast(int) 0x515BAD24, cast(int) 0x7B9479BF, cast(int)
0x763BD6EB,
cast(int) 0x37392EB3, cast(int) 0xCC115979, cast(int) 0x8026E297, cast(int)
0xF42E312D,
cast(int) 0x6842ADA7, cast(int) 0xC66A2B3B, cast(int) 0x12754CCC, cast(int)
0x782EF11C,
cast(int) 0x6A124237, cast(int) 0xB79251E7, cast(int) 0x06A1BBE6, cast(int)
0x4BFB6350,
cast(int) 0x1A6B1018, cast(int) 0x11CAEDFA, cast(int) 0x3D25BDD8, cast(int)
0xE2E1C3C9,
cast(int) 0x44421659, cast(int) 0x0A121386, cast(int) 0xD90CEC6E, cast(int)
0xD5ABEA2A,
cast(int) 0x64AF674E, cast(int) 0xDA86A85F, cast(int) 0xBEBFE988, cast(int)
0x64E4C3FE,
cast(int) 0x9DBC8057, cast(int) 0xF0F7C086, cast(int) 0x60787BF8, cast(int)
0x6003604D,
cast(int) 0xD1FD8346, cast(int) 0xF6381FB0, cast(int) 0x7745AE04, cast(int)
0xD736FCCC,
cast(int) 0x83426B33, cast(int) 0xF01EAB71, cast(int) 0xB0804187, cast(int)
0x3C005E5F,
cast(int) 0x77A057BE, cast(int) 0xBDE8AE24, cast(int) 0x55464299, cast(int)
0xBF582E61,
cast(int) 0x4E58F48F, cast(int) 0xF2DDFDA2, cast(int) 0xF474EF38, cast(int)
0x8789BDC2,
cast(int) 0x5366F9C3, cast(int) 0xC8B38E74, cast(int) 0xB475F255, cast(int)
0x46FCD9B9,
cast(int) 0x7AEB2661, cast(int) 0x8B1DDF84, cast(int) 0x846A0E79, cast(int)
0x915F95E2,
cast(int) 0x466E598E, cast(int) 0x20B45770, cast(int) 0x8CD55591, cast(int)
0xC902DE4C,
cast(int) 0xB90BACE1, cast(int) 0xBB8205D0, cast(int) 0x11A86248, cast(int)
0x7574A99E,
cast(int) 0xB77F19B6, cast(int) 0xE0A9DC09, cast(int) 0x662D09A1, cast(int)
0xC4324633,
cast(int) 0xE85A1F02, cast(int) 0x09F0BE8C, cast(int) 0x4A99A025, cast(int)
0x1D6EFE10,
cast(int) 0x1AB93D1D, cast(int) 0x0BA5A4DF, cast(int) 0xA186F20F, cast(int)
0x2868F169,
cast(int) 0xDCB7DA83, cast(int) 0x573906FE, cast(int) 0xA1E2CE9B, cast(int)
0x4FCD7F52,
cast(int) 0x50115E01, cast(int) 0xA70683FA, cast(int) 0xA002B5C4, cast(int)
0x0DE6D027,
cast(int) 0x9AF88C27, cast(int) 0x773F8641, cast(int) 0xC3604C06, cast(int)
0x61A806B5,
cast(int) 0xF0177A28, cast(int) 0xC0F586E0, cast(int) 0x006058AA, cast(int)
0x30DC7D62,
cast(int) 0x11E69ED7, cast(int) 0x2338EA63, cast(int) 0x53C2DD94, cast(int)
0xC2C21634,
cast(int) 0xBBCBEE56, cast(int) 0x90BCB6DE, cast(int) 0xEBFC7DA1, cast(int)
0xCE591D76,
cast(int) 0x6F05E409, cast(int) 0x4B7C0188, cast(int) 0x39720A3D, cast(int)
0x7C927C24,
cast(int) 0x86E3725F, cast(int) 0x724D9DB9, cast(int) 0x1AC15BB4, cast(int)
0xD39EB8FC,
cast(int) 0xED545578, cast(int) 0x08FCA5B5, cast(int) 0xD83D7CD3, cast(int)
0x4DAD0FC4,
cast(int) 0x1E50EF5E, cast(int) 0xB161E6F8, cast(int) 0xA28514D9, cast(int)
0x6C51133C,
cast(int) 0x6FD5C7E7, cast(int) 0x56E14EC4, cast(int) 0x362ABFCE, cast(int)
0xDDC6C837,
cast(int) 0xD79A3234, cast(int) 0x92638212, cast(int) 0x670EFA8E, cast(int)
0x406000E0
];

private const int[]
KS3 = [
cast(int) 0x3A39CE37, cast(int) 0xD3FAF5CF, cast(int) 0xABC27737, cast(int)
0x5AC52D1B,
cast(int) 0x5CB0679E, cast(int) 0x4FA33742, cast(int) 0xD3822740, cast(int)
0x99BC9BBE,
cast(int) 0xD5118E9D, cast(int) 0xBF0F7315, cast(int) 0xD62D1C7E, cast(int)
0xC700C47B,
cast(int) 0xB78C1B6B, cast(int) 0x21A19045, cast(int) 0xB26EB1BE, cast(int)
0x6A366EB4,
cast(int) 0x5748AB2F, cast(int) 0xBC946E79, cast(int) 0xC6A376D2, cast(int)
0x6549C2C8,
cast(int) 0x530FF8EE, cast(int) 0x468DDE7D, cast(int) 0xD5730A1D, cast(int)
0x4CD04DC6,
cast(int) 0x2939BBDB, cast(int) 0xA9BA4650, cast(int) 0xAC9526E8, cast(int)
0xBE5EE304,
cast(int) 0xA1FAD5F0, cast(int) 0x6A2D519A, cast(int) 0x63EF8CE2, cast(int)
0x9A86EE22,
cast(int) 0xC089C2B8, cast(int) 0x43242EF6, cast(int) 0xA51E03AA, cast(int)
0x9CF2D0A4,
cast(int) 0x83C061BA, cast(int) 0x9BE96A4D, cast(int) 0x8FE51550, cast(int)
0xBA645BD6,
cast(int) 0x2826A2F9, cast(int) 0xA73A3AE1, cast(int) 0x4BA99586, cast(int)
0xEF5562E9,
cast(int) 0xC72FEFD3, cast(int) 0xF752F7DA, cast(int) 0x3F046F69, cast(int)
0x77FA0A59,
cast(int) 0x80E4A915, cast(int) 0x87B08601, cast(int) 0x9B09E6AD, cast(int)
0x3B3EE593,
cast(int) 0xE990FD5A, cast(int) 0x9E34D797, cast(int) 0x2CF0B7D9, cast(int)
0x022B8B51,
cast(int) 0x96D5AC3A, cast(int) 0x017DA67D, cast(int) 0xD1CF3ED6, cast(int)
0x7C7D2D28,
cast(int) 0x1F9F25CF, cast(int) 0xADF2B89B, cast(int) 0x5AD6B472, cast(int)
0x5A88F54C,
cast(int) 0xE029AC71, cast(int) 0xE019A5E6, cast(int) 0x47B0ACFD, cast(int)
0xED93FA9B,
cast(int) 0xE8D3C48D, cast(int) 0x283B57CC, cast(int) 0xF8D56629, cast(int)
0x79132E28,
cast(int) 0x785F0191, cast(int) 0xED756055, cast(int) 0xF7960E44, cast(int)
0xE3D35E8C,
cast(int) 0x15056DD4, cast(int) 0x88F46DBA, cast(int) 0x03A16125, cast(int)
0x0564F0BD,
cast(int) 0xC3EB9E15, cast(int) 0x3C9057A2, cast(int) 0x97271AEC, cast(int)
0xA93A072A,
cast(int) 0x1B3F6D9B, cast(int) 0x1E6321F5, cast(int) 0xF59C66FB, cast(int)
0x26DCF319,
cast(int) 0x7533D928, cast(int) 0xB155FDF5, cast(int) 0x03563482, cast(int)
0x8ABA3CBB,
cast(int) 0x28517711, cast(int) 0xC20AD9F8, cast(int) 0xABCC5167, cast(int)
0xCCAD925F,
cast(int) 0x4DE81751, cast(int) 0x3830DC8E, cast(int) 0x379D5862, cast(int)
0x9320F991,
cast(int) 0xEA7A90C2, cast(int) 0xFB3E7BCE, cast(int) 0x5121CE64, cast(int)
0x774FBE32,
cast(int) 0xA8B6E37E, cast(int) 0xC3293D46, cast(int) 0x48DE5369, cast(int)
0x6413E680,
cast(int) 0xA2AE0810, cast(int) 0xDD6DB224, cast(int) 0x69852DFD, cast(int)
0x09072166,
cast(int) 0xB39A460A, cast(int) 0x6445C0DD, cast(int) 0x586CDECF, cast(int)
0x1C20C8AE,
cast(int) 0x5BBEF7DD, cast(int) 0x1B588D40, cast(int) 0xCCD2017F, cast(int)
0x6BB4E3BB,
cast(int) 0xDDA26A7E, cast(int) 0x3A59FF45, cast(int) 0x3E350A44, cast(int)
0xBCB4CDD5,
cast(int) 0x72EACEA8, cast(int) 0xFA6484BB, cast(int) 0x8D6612AE, cast(int)
0xBF3C6F47,
cast(int) 0xD29BE463, cast(int) 0x542F5D9E, cast(int) 0xAEC2771B, cast(int)
0xF64E6370,
cast(int) 0x740E0D8D, cast(int) 0xE75B1357, cast(int) 0xF8721671, cast(int)
0xAF537D5D,
cast(int) 0x4040CB08, cast(int) 0x4EB4E2CC, cast(int) 0x34D2466A, cast(int)
0x0115AF84,
cast(int) 0xE1B00428, cast(int) 0x95983A1D, cast(int) 0x06B89FB4, cast(int)
0xCE6EA048,
cast(int) 0x6F3F3B82, cast(int) 0x3520AB82, cast(int) 0x011A1D4B, cast(int)
0x277227F8,
cast(int) 0x611560B1, cast(int) 0xE7933FDC, cast(int) 0xBB3A792B, cast(int)
0x344525BD,
cast(int) 0xA08839E1, cast(int) 0x51CE794B, cast(int) 0x2F32C9B7, cast(int)
0xA01FBAC9,
cast(int) 0xE01CC87E, cast(int) 0xBCC7D1F6, cast(int) 0xCF0111C3, cast(int)
0xA1E8AAC7,
cast(int) 0x1A908749, cast(int) 0xD44FBD9A, cast(int) 0xD0DADECB, cast(int)
0xD50ADA38,
cast(int) 0x0339C32A, cast(int) 0xC6913667, cast(int) 0x8DF9317C, cast(int)
0xE0B12B4F,
cast(int) 0xF79E59B7, cast(int) 0x43F5BB3A, cast(int) 0xF2D519FF, cast(int)
0x27D9459C,
cast(int) 0xBF97222C, cast(int) 0x15E6FC2A, cast(int) 0x0F91FC71, cast(int)
0x9B941525,
cast(int) 0xFAE59361, cast(int) 0xCEB69CEB, cast(int) 0xC2A86459, cast(int)
0x12BAA8D1,
cast(int) 0xB6C1075E, cast(int) 0xE3056A0C, cast(int) 0x10D25065, cast(int)
0xCB03A442,
cast(int) 0xE0EC6E0E, cast(int) 0x1698DB3B, cast(int) 0x4C98A0BE, cast(int)
0x3278E964,
cast(int) 0x9F1F9532, cast(int) 0xE0D392DF, cast(int) 0xD3A0342B, cast(int)
0x8971F21E,
cast(int) 0x1B0A7441, cast(int) 0x4BA3348C, cast(int) 0xC5BE7120, cast(int)
0xC37632D8,
cast(int) 0xDF359F8D, cast(int) 0x9B992F2E, cast(int) 0xE60B6F47, cast(int)
0x0FE3F11D,
cast(int) 0xE54CDA54, cast(int) 0x1EDAD891, cast(int) 0xCE6279CF, cast(int)
0xCD3E7E6F,
cast(int) 0x1618B166, cast(int) 0xFD2C1D05, cast(int) 0x848FD2C5, cast(int)
0xF6FB2299,
cast(int) 0xF523F357, cast(int) 0xA6327623, cast(int) 0x93A83531, cast(int)
0x56CCCD02,
cast(int) 0xACF08162, cast(int) 0x5A75EBB5, cast(int) 0x6E163697, cast(int)
0x88D273CC,
cast(int) 0xDE966292, cast(int) 0x81B949D0, cast(int) 0x4C50901B, cast(int)
0x71C65614,
cast(int) 0xE6C6C7BD, cast(int) 0x327A140A, cast(int) 0x45E1D006, cast(int)
0xC3F27B9A,
cast(int) 0xC9AA53FD, cast(int) 0x62A80F00, cast(int) 0xBB25BFE2, cast(int)
0x35BDD2F6,
cast(int) 0x71126905, cast(int) 0xB2040222, cast(int) 0xB6CBCF7C, cast(int)
0xCD769C2B,
cast(int) 0x53113EC0, cast(int) 0x1640E3D3, cast(int) 0x38ABBD60, cast(int)
0x2547ADF0,
cast(int) 0xBA38209C, cast(int) 0xF746CE76, cast(int) 0x77AFA1C5, cast(int)
0x20756060,
cast(int) 0x85CBFE4E, cast(int) 0x8AE88DD8, cast(int) 0x7AAAF9B0, cast(int)
0x4CF9AA7E,
cast(int) 0x1948C25C, cast(int) 0x02FB8A8C, cast(int) 0x01C36AE4, cast(int)
0xD6EBE1F9,
cast(int) 0x90D4F869, cast(int) 0xA65CDEA0, cast(int) 0x3F09252D, cast(int)
0xC208E69F,
cast(int) 0xB74E6132, cast(int) 0xCE77E25B, cast(int) 0x578FDFE3, cast(int)
0x3AC372E6
];

//====================================
// Useful constants
//====================================
private static const int    ROUNDS = 16;
private static const int    BLOCK_SIZE = 8;  // bytes = 64 bits
private static const int    SBOX_SK = 256;
private static const int    P_SZ = ROUNDS+2;
private const int[] S0, S1, S2, S3;     // the s-boxes
private const int[] P;                  // the p-array
private bool encrypting = false;
private ubyte[] workingKey = null;

public this()
{
S0 = new int[SBOX_SK];
S1 = new int[SBOX_SK];
S2 = new int[SBOX_SK];
S3 = new int[SBOX_SK];
P = new int[P_SZ];
}

public this(bool encrypting, ubyte[] key)
{
S0 = new int[SBOX_SK];
S1 = new int[SBOX_SK];
S2 = new int[SBOX_SK];
S3 = new int[SBOX_SK];
P = new int[P_SZ];
init(encrypting, key);
}

/**
* initialise a Blowfish cipher.
*
*  param forEncryption whether or not we are for encryption.
*  param params the parameters required to set up the cipher.
*  exception IllegalArgumentException if the params argument is
* inappropriate.
*/
public void init(bool encrypting, ubyte[] key=null)
{
if (key != null)
{
this.encrypting = encrypting;
this.workingKey = key;
setKey(this.workingKey);
}
else
throw new Exception("invalid parameter passed to Blowfish init - key");
}

public char[] getAlgorithmName()
{
return "Blowfish";
}

public int processBlock(ubyte[] inBytes, int inOff, inout ubyte[] outBytes, int
outOff)
{
if (workingKey == null) {
throw new Exception("Blowfish not initialised");
}
if(inBytes.length == 0) {
throw new Exception("input buffer too short");
}
if ((inOff + BLOCK_SIZE) > inBytes.length) {
throw new Exception("input buffer too short");
}
if ((outOff + BLOCK_SIZE) > outBytes.length) {
outBytes.length = (outOff + BLOCK_SIZE);
}
if (encrypting) {
encryptBlock(inBytes, inOff, outBytes, outOff);
}
else {
decryptBlock(inBytes, inOff, outBytes, outOff);
}
return BLOCK_SIZE;
}

public int processBlock(ubyte[] inBytes, inout ubyte[] outBytes)
{
int pad = 0; int inOff = 0;
if(workingKey == null) {
throw new Exception("Blowfish not initialised");
}
if(inBytes.length == 0) {
throw new Exception("input buffer too short");
}
pad = inBytes.length % BLOCK_SIZE;
if(pad != 0) {
pad = BLOCK_SIZE - pad;
while(inOff < pad) {
inBytes ~= 0x0;
inOff++;
}
}
outBytes.length = inBytes.length;
inOff = 0;
while(inOff < inBytes.length) {
if(encrypting) {
encryptBlock(inBytes, inOff, outBytes, inOff);
}
else {
decryptBlock(inBytes, inOff, outBytes, inOff);
}
inOff += BLOCK_SIZE;
}
return inBytes.length;
}

public void reset()
{
}

public int getBlockSize()
{
return BLOCK_SIZE;
}

//==================================
// Private Implementation
//==================================

private int F(int x)
{
return (((S0[(cast(uint) x >> 24)] + S1[(cast(uint) x >> 16) & 0xff]) ^
S2[(cast(uint) x >> 8) & 0xff]) + S3[x & 0xff]);
}

/**
* apply the encryption cycle to each value pair in the table.
*/
private void processTable(int xl, int xr, int[] table)
{
int size = table.length;
for (int s = 0; s < size; s += 2)
{
xl ^= P[0];
for (int i = 1; i < ROUNDS; i += 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i + 1];
}
xr ^= P[ROUNDS + 1];
table[s] = xr;
table[s + 1] = xl;
xr = xl;            // end of cycle swap
xl = table[s];
}
}

private void setKey(ubyte[] key)
{
/*
* - comments are from _Applied Crypto_, Schneier, p338
* please be careful comparing the two, AC numbers the
* arrays from 1, the enclosed code from 0.
*
* (1)
* Initialise the S-boxes and the P-array, with a fixed string
* This string contains the hexadecimal digits of pi (3.141...)
*/
//Array.Copy(KS0, 0, S0, 0, SBOX_SK);
S0[0..SBOX_SK] = KS0;
//Array.Copy(KS1, 0, S1, 0, SBOX_SK);
S1[0..SBOX_SK] = KS1;
//Array.Copy(KS2, 0, S2, 0, SBOX_SK);
S2[0..SBOX_SK] = KS2;
//Array.Copy(KS3, 0, S3, 0, SBOX_SK);
S3[0..SBOX_SK] = KS3;

//Array.Copy(KP, 0, P, 0, P_SZ);
P[0..P_SZ] = KP;

/*
* (2)
* Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
* second 32-bits of the key, and so on for all bits of the key
* (up to P[17]).  Repeatedly cycle through the key bits until the
* entire P-array has been XOR-ed with the key bits
*/
int keyLength = key.length;
int keyIndex = 0;

for (int i=0; i < P_SZ; i++)
{
// get the 32 bits of the key, in 4 * 8 bit chunks
int data = cast(int) 0x0000000;
for (int j=0; j < 4; j++)
{
// create a 32 bit block
data = (data << 8) | (key[keyIndex++] & 0xff);

// wrap when we get to the end of the key
if (keyIndex >= keyLength)
{
keyIndex = 0;
}
}
// XOR the newly created 32 bit chunk onto the P-array
P[i] ^= data;
}

/*
* (3)
* Encrypt the all-zero string with the Blowfish algorithm, using
* the subkeys described in (1) and (2)
*
* (4)
* Replace P1 and P2 with the output of step (3)
*
* (5)
* Encrypt the output of step(3) using the Blowfish algorithm,
* with the modified subkeys.
*
* (6)
* Replace P3 and P4 with the output of step (5)
*
* (7)
* Continue the process, replacing all elements of the P-array
* and then all four S-boxes in order, with the output of the
* continuously changing Blowfish algorithm
*/
processTable(0, 0, P);
processTable(P[P_SZ - 2], P[P_SZ - 1], S0);
processTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
processTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
processTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
}

/**
* Encrypt the given input starting at the given offset and place
* the result in the provided buffer starting at the given offset.
* The input will be an exact multiple of our blocksize.
*/
private void encryptBlock(ubyte[] src, int srcIndex, ubyte[] dst, int dstIndex)
{
int xl = BytesTo32bits(src, srcIndex);
int xr = BytesTo32bits(src, srcIndex+4);
xl ^= P[0];
for (int i = 1; i < ROUNDS; i += 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i + 1];
}
xr ^= P[ROUNDS + 1];
Bits32ToBytes(xr, dst, dstIndex);
Bits32ToBytes(xl, dst, dstIndex + 4);
}

/**
* Decrypt the given input starting at the given offset and place
* the result in the provided buffer starting at the given offset.
* The input will be an exact multiple of our blocksize.
*/
private void decryptBlock(ubyte[] src, int srcIndex, ubyte[] dst, int dstIndex)
{
int xl = BytesTo32bits(src, srcIndex);
int xr = BytesTo32bits(src, srcIndex + 4);
xl ^= P[ROUNDS + 1];
for (int i = ROUNDS; i > 0 ; i -= 2)
{
xr ^= F(xl) ^ P[i];
xl ^= F(xr) ^ P[i - 1];
}
xr ^= P[0];
Bits32ToBytes(xr, dst, dstIndex);
Bits32ToBytes(xl, dst, dstIndex+4);
}

private int BytesTo32bits(ubyte[] b, int i)
{
return ((b[i]   & 0xff) << 24) |
((b[i+1] & 0xff) << 16) |
((b[i+2] & 0xff) << 8) |
((b[i+3] & 0xff));
}

private void Bits32ToBytes(int inData,  ubyte[] b, int offset)
{
b[offset + 3] = cast(ubyte)inData;
b[offset + 2] = cast(ubyte)(inData >> 8);
b[offset + 1] = cast(ubyte)(inData >> 16);
b[offset]     = cast(ubyte)(inData >> 24);
}
}

int main() {
ubyte[] bkey;
ubyte[] ins;
ubyte[] outs;
ubyte[] xx;
bkey.length = 8; ins.length = 17; outs.length = 32;   xx.length = 32;
bkey = cast(ubyte[])"xxxxxxxx";
ins = cast(ubyte[])"ttttttttttttttttz";

/*  working
BlowfishEngine bl;
bl = new BlowfishEngine();
bl.init(true, bkey);
bl.processBlock(ins, outs);
printf(">|  %s\n", toStringz(cast(char[])outs));

BlowfishEngine bl1;
bl1 = new BlowfishEngine();
bl1.init(false, bkey);
bl1.processBlock(outs, xx);
printf(">|  %s\n", toStringz(cast(char[])xx));

return 1;
}
Mar 23 2006
next sibling parent Dejan Lekic <dejan nu6.org> writes:
Can You _ATTACH_ file next time?
Mar 23 2006
prev sibling next sibling parent reply r <r_member pathlink.com> writes:
sorry i tried to attach, but it did not work. little over 19k encryped old
datagrams work to be decrypted, encrypted and compared.

the library (c#) has a wealth of algos and i am converting rc4 and shas since i
need them to go from modula-2 to d. maybe someone else sees the need to convert
some others ...
i use the cryptosys pki lib for the rest i don't have yet and try to attach the
d header.

funny i write that now for the second time, i hope it will end up in the ng

r
Mar 23 2006
next sibling parent r <r_member pathlink.com> writes:
sorry forgot the link http://www.cryptosys.net/pki/

r
Mar 23 2006
prev sibling parent r <r_member pathlink.com> writes:
sorry forgot the link http://www.cryptosys.net/pki/ for cryptolib

r
Mar 23 2006
prev sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/

The library "deimos" never really got off the ground, I think it may be  
tome to salvage what can be salvaged from deimos and put it somewhere  
else, perhaps in "Ares", Shaun? If the crypto stuff is unsuitable for any  
reason let me know and I can re-work it.

Regan
Mar 23 2006
next sibling parent reply Brad Anderson <brad dsource.dot.org> writes:
Regan Heath wrote:
 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/
 
 The library "deimos" never really got off the ground, I think it may be 
 tome to salvage what can be salvaged from deimos and put it somewhere 
 else, perhaps in "Ares", Shaun? If the crypto stuff is unsuitable for
 any  reason let me know and I can re-work it.
 
 Regan

Woo Hoo! Definitely send the crypto stuff to Ares if Sean will have it. I have a blowfish algorithm that I'm working on - not sure how it stacks up with 'r's version, but a consistent API for all of the crypto algorithms would be great. encryptString(char|wchar|dchar) decryptString(char|wchar|dchar) encryptFile() decryptFile() I'm not sure if this 'consistent' API is possible given the differences in the crypto libs, or if it's a good idea at all. BA
Mar 23 2006
next sibling parent Derek Parnell <derek psych.ward> writes:
On Thu, 23 Mar 2006 17:00:40 -0600, Brad Anderson wrote:

 Regan Heath wrote:
 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/
 
 The library "deimos" never really got off the ground, I think it may be 
 tome to salvage what can be salvaged from deimos and put it somewhere 
 else, perhaps in "Ares", Shaun? If the crypto stuff is unsuitable for
 any  reason let me know and I can re-work it.
 
 Regan

Woo Hoo! Definitely send the crypto stuff to Ares if Sean will have it. I have a blowfish algorithm that I'm working on - not sure how it stacks up with 'r's version, but a consistent API for all of the crypto algorithms would be great. encryptString(char|wchar|dchar) decryptString(char|wchar|dchar) encryptFile() decryptFile() I'm not sure if this 'consistent' API is possible given the differences in the crypto libs, or if it's a good idea at all.

Need to cater for non-text data too. encryptData(ubyte[]) decryptData(ubyte[]) -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 24/03/2006 10:03:21 AM
Mar 23 2006
prev sibling parent Sean Kelly <sean f4.ca> writes:
Brad Anderson wrote:
 Regan Heath wrote:
 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/

 The library "deimos" never really got off the ground, I think it may be 
 tome to salvage what can be salvaged from deimos and put it somewhere 
 else, perhaps in "Ares", Shaun? If the crypto stuff is unsuitable for
 any  reason let me know and I can re-work it.

Woo Hoo! Definitely send the crypto stuff to Ares if Sean will have it. I have a blowfish algorithm that I'm working on - not sure how it stacks up with 'r's version, but a consistent API for all of the crypto algorithms would be great. encryptString(char|wchar|dchar) decryptString(char|wchar|dchar) encryptFile() decryptFile() I'm not sure if this 'consistent' API is possible given the differences in the crypto libs, or if it's a good idea at all.

I think it would be useful to have both standalone functions and filters for IO. However, I think "standalone functions" may be a bit misleading, as some attention should probably be paid to supporting different encoding schemes and such with the same basic interface. I don't have a tremendous amount of experience here, but I suppose the .NET API might be one model to consider. The easiest thing in Ares terms might be to consider this an add-on library, since crypto is probably not so essential that it should be considered a core component. So interface consistency would be an ultimate goal, but it wouldn't be tied to the core library release schedule. This would also make it easier to offer this as a standalone library for those who prefer Phobos. Does this sound reasonable? Sean
Mar 23 2006
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Regan Heath wrote:
 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/
 
 The library "deimos" never really got off the ground, I think it may be 
 tome to salvage what can be salvaged from deimos and put it somewhere 
 else, perhaps in "Ares", Shaun? If the crypto stuff is unsuitable for 
 any reason let me know and I can re-work it.

That's a bit past the level of what I've been focusing on, but it's certainly a candidate for eventual inclusion. Sean
Mar 23 2006
parent reply kris <foo bar.com> writes:
Sean Kelly wrote:
 Regan Heath wrote:
 
 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/

 The library "deimos" never really got off the ground, I think it may 
 be tome to salvage what can be salvaged from deimos and put it 
 somewhere else, perhaps in "Ares", Shaun? If the crypto stuff is 
 unsuitable for any reason let me know and I can re-work it.

That's a bit past the level of what I've been focusing on, but it's certainly a candidate for eventual inclusion. Sean

I've seriously considered adding a crypto package to Mango; particularly in support of network-oriented apps (MD4, MD5, SHA1, some SSL support, and so on). Perhaps that might be a reasonable home for the time being? Should only need support for void[], right?
Mar 23 2006
next sibling parent Sean Kelly <sean f4.ca> writes:
kris wrote:
 Sean Kelly wrote:
 Regan Heath wrote:

 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/

 The library "deimos" never really got off the ground, I think it may 
 be tome to salvage what can be salvaged from deimos and put it 
 somewhere else, perhaps in "Ares", Shaun? If the crypto stuff is 
 unsuitable for any reason let me know and I can re-work it.

That's a bit past the level of what I've been focusing on, but it's certainly a candidate for eventual inclusion.

I've seriously considered adding a crypto package to Mango; particularly in support of network-oriented apps (MD4, MD5, SHA1, some SSL support, and so on). Perhaps that might be a reasonable home for the time being?

Definately. As I mentioned in my other post, I'd like to have a crypto filter anyway :-)
 Should only need support for void[], right?

Aye. Sean
Mar 23 2006
prev sibling next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 23 Mar 2006 15:15:03 -0800, kris <foo bar.com> wrote:
 Sean Kelly wrote:
 Regan Heath wrote:

 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/

 The library "deimos" never really got off the ground, I think it may  
 be tome to salvage what can be salvaged from deimos and put it  
 somewhere else, perhaps in "Ares", Shaun? If the crypto stuff is  
 unsuitable for any reason let me know and I can re-work it.

certainly a candidate for eventual inclusion. Sean

I've seriously considered adding a crypto package to Mango; particularly in support of network-oriented apps (MD4, MD5, SHA1, some SSL support, and so on). Perhaps that might be a reasonable home for the time being? Should only need support for void[], right?

(this is essentially a reply to everyone on this thread) Yes, I believe so. Kris you're welcome to place the crypto code I wrote into Mango. I believe I put a BSD stlye license on it, let me know if that is a problem. The interface I used is essentially the same as the std.md5 one in phobos. It's all done with structs and mixins (which essentially emulates class inheritance). The reason I used structs was to make it easy to copy/store a hash state i.e. you just assign one MD5 to another and it copies the context data. Not sure if that is a good enough reason now, perhaps classes with dup methods would be better. Essentially there are some basic methods: void start(); void update(void[] input); void finish(T digest); void sum(T digest, void[] input); which are mixed into the real implementation. The idea behind these methods is that you can call "sum" if you have all the data at once (sum calls the other 3, meaning you cannot mix it with calls to the other), or you can call start, then update any number of times, and finally finish. The latter 3 methods make it easy to integrate with a stream, for example. Each real implementation defines a trasform method in the form: void transform(ubyte[] input); which is called by the mixed methods to process the data, in addition the following methods: void padMessage(ubyte[] at); void padLength(ubyte[] at, ulong length); are called to perform the padding, and: void extend(); was required to handle MD2 being a little different to the others. This design pattern and interface works for: MD2, MD4, MD5, SHA0, SHA1, SHA256, SHA512, and Tiger. Does it work for blowfish as well? What does the .NET API look like? Regan
Mar 23 2006
parent reply kris <foo bar.com> writes:
Regan Heath wrote:
 On Thu, 23 Mar 2006 15:15:03 -0800, kris <foo bar.com> wrote:
 
 Sean Kelly wrote:

 Regan Heath wrote:

 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/

 The library "deimos" never really got off the ground, I think it 
 may  be tome to salvage what can be salvaged from deimos and put it  
 somewhere else, perhaps in "Ares", Shaun? If the crypto stuff is  
 unsuitable for any reason let me know and I can re-work it.

That's a bit past the level of what I've been focusing on, but it's certainly a candidate for eventual inclusion. Sean

I've seriously considered adding a crypto package to Mango; particularly in support of network-oriented apps (MD4, MD5, SHA1, some SSL support, and so on). Perhaps that might be a reasonable home for the time being? Should only need support for void[], right?

(this is essentially a reply to everyone on this thread) Yes, I believe so. Kris you're welcome to place the crypto code I wrote into Mango. I believe I put a BSD stlye license on it, let me know if that is a problem. The interface I used is essentially the same as the std.md5 one in phobos. It's all done with structs and mixins (which essentially emulates class inheritance). The reason I used structs was to make it easy to copy/store a hash state i.e. you just assign one MD5 to another and it copies the context data. Not sure if that is a good enough reason now, perhaps classes with dup methods would be better. Essentially there are some basic methods: void start(); void update(void[] input); void finish(T digest); void sum(T digest, void[] input); which are mixed into the real implementation. The idea behind these methods is that you can call "sum" if you have all the data at once (sum calls the other 3, meaning you cannot mix it with calls to the other), or you can call start, then update any number of times, and finally finish. The latter 3 methods make it easy to integrate with a stream, for example. Each real implementation defines a trasform method in the form: void transform(ubyte[] input); which is called by the mixed methods to process the data, in addition the following methods: void padMessage(ubyte[] at); void padLength(ubyte[] at, ulong length); are called to perform the padding, and: void extend(); was required to handle MD2 being a little different to the others. This design pattern and interface works for: MD2, MD4, MD5, SHA0, SHA1, SHA256, SHA512, and Tiger. Does it work for blowfish as well? What does the .NET API look like? Regan

That all sounds great (though I'll admit to being more than a bit leery of D mixins). I'll take a look at the license, and get back to you via the Deimos forum? - Kris
Mar 23 2006
parent reply "Regan Heath" <regan netwin.co.nz> writes:
------------0HfOWIEbrFHHiydfw9h323
Content-Type: text/plain; format=flowed; delsp=yes; charset=iso-8859-15
Content-Transfer-Encoding: 8bit

On Thu, 23 Mar 2006 16:20:02 -0800, kris <foo bar.com> wrote:
 That all sounds great (though I'll admit to being more than a bit leery  
 of D mixins). I'll take a look at the license, and get back to you via  
 the Deimos forum?

I just went ahead and converted my hashing code from the struct+mixin approach to a class+factory approach. The source included in the attached zip file hash.zip is public domain, this includes: base.d factory.d md2.d md4.d md5.d sha0.d sha1.d sha256.d sha512.d tiger.d I would very much like to see my code appear in any library that needs/wants it. It'd be nice to get a mention somewhere too, y'know for my ego n'all. Regan ------------0HfOWIEbrFHHiydfw9h323 Content-Disposition: attachment; filename=hash.zip Content-Type: application/zip; name=hash.zip Content-Transfer-Encoding: Base64 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 3e2Lh49v37198/oVlZxi8M6ap48NpVfxdXjjX7t3tmR8+t3j+a7b+ddPXnq6GX/p Mw+ftR8/9L/5491/m2ejSOGhD1ws6hiP399si/L1zY126vjn89On+v189rn96X7i sdd7cW69/9ZwO3h0z9ePn9mXL+v9yx/n++/vf+CvzW4eTwf9Z5cvj2O+ePDgzcOv 5AwP/3nz+98/3N3l8HzIZ72i2Vx+/tvn/+jxR9zV9omvTnr/sb7/tD58/ElOevf+ 58/7Xh5Of//Tz/VFfdFe9K/lw2/Ldze/PPwn++3uwctf/Hh3f//jfPd+3NX3KTy7 HO3FL88fv61H5DGXa/miHR/Zh4/68ZH77vGnuMhndxe33dyh5T409pu7r77Ck+Tv L2367uYPN+b5zd/MP/2x/zA5nD775aGDfsH2zy738OKXF8/uvvnGPP8n8S/5D/b5 P8l/SY9mfKs4S/365nKtX9/wxbSvb/gy+buLFbeFL748uv3ledeb/3x9c/vG+Cg3 v/vVncpd8sluvtK3/XCOX759aC1fyJN77GKXJ8bh5DX+/RDvb/qLh67Z7NMfHP/4 OlTsdvIcjebmD3+4edbsb8vzhz85/Okp6OzTXdrLxw+f3w881Q+fHzv3TX1xc/5n 0//Zn1rwL09/+Onzj3I1/eY/f/PYiOrN7+Bg++3T7fQX5vl3cOi9Oz5yDx/546Pw 8FE4P2K7x7b11Tf6O/vrI/hfnyc82Vn1oZfD/vYbvo//sYsuDe1/3UOX/vQ/ctKD yx9bLhrWC/7y6/0Nf17xjf3VN/3SZ39BY7r+5ulo/s8eLfzZo8U/e7T0Z4+W9ze/ dtjZW7cr5P75nrlx8FHwTMwvr6L+6+ubBzN0Mm5O3PceP0G3+oo/sfKJfzyU40M9 e/b/83fPf/97i+7/aBEej+LlN/HxKEE+SY9HiXKU8N3zP/zBeTlKfjxKkt+Yx6Pk 747r/d3D9T4dJV9di3s8irr+rx6u/7je3z1c79NR3NW1xMejqOv/6uH6j+v93cP1 Xlx8nZ0fH9yh6i7y6UFPPSR15Ev+oau12dxXnmR6nPjwH//28tXNb//xiweb2oML zfjpgq9ldrGxbPN0pOz6iG16M0ZcfXixcvtIaRhLjfxKi/LyVWz8eaQ+iHJZazi7 yNI+UthHyjH7ajtlU4yj6cQmnkdqNkGVpEbO1eL7PlLaRwqpFD/nNIFsLNmITT6P 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 DyFINZ5R9IZF21MlL2w05UfePXIynfLbkUiszjiO3NOCWTxd1vrcNle1tZbfhDKB cNnMp2oyWJ3j45l4zy20cmjN9FT1zXuNqH6XE/eFjlYeqn9ahQmrw+OV323B0yQJ CSg/VQjBRo+P84IUX+vkF9n7p3VHsDprsootzQcuNacib4iDjfI4ZFwAZEw/7Syy vh38eI7Wrjb4LXoFsQKeCmKjtYoPXLjW42qI91a8qd7PmaB6p0uEeMdVMGKjZ91m HLzdJeAVKXTK3Z3MCdAMAZ6r/DoR2QEXNjqqrNTx0OLKOXXZQ5Tp+DiStaAffh1Z 5LnsITZ6ZrmZbrIp2cTq09MKS1id4+PgdhtyBMGWvUYCNrq2dkRIi+ABZsWVp3W2 vLrkaOP28motyNHI7wSNYqOjSvHO+WWzA74vkt5yMicEhvGAt+zRXqKVNndhzi9/ 893XX/7my998fn93fz8/3d/8/Rdf/uaLT/f1/q7f9B/qx2+/+/a7m0/3H+/ef//p 5pubb/HtF3/xFy8u/wIvPf7pr+++nx8f//zq9Zu3727/6V/9P//v//fP/vm/+Jf/ 6l//mz/+9b/9d//+P/zH/wR7YN33P9z9l7/58af3H37+rx8/3X/+27/75U//DU3E 8wt7Cn31u//pYb7588f5ah/ovLKb3928urmtuL1/Mf/u5q/qpx9ubj+/7/d3H96/ uGl/uvk3Hz59unn1fsyPnz68v6nvx827H+9uXt/9UH/6P3SYFzc/f/zQ5xwXP35Y D4f544d1/3f147x5975//NPPfKAb/+LmTf2pfbwb38+X/1fP/oLfnZxe/h96rP/b zQJXwW31V43z4/z0+cf73ThduEU0MW+Sf/UGmO9ssim9y+m1ff2aXLy9Rcx/+869 DaCM8C6/ery/WxfLG/uulGDDq9fuVXT51Wvk/NvbN/F1eX0Lzr/Nr0Fnb3jXuWgf f0a3xtxG5OzsvDFv37qcXr1+7cub8u51evvuDTQImTfQyLf01r1+e/v4s5JvcQ4e Ny444m0O2bx1b26LNe/S21t695oXqgRk7vAqvvIlPf4Moubt64K06N+9fvMOyuTt rX3zFkBgU4xv34GuCvG6FIjZW6BAfvyZeQNJ/MoE6E9+tdArm7J9ywe+fevoVXbx He4c8vytf/P2tTf+8WfvXuPO7Nv46vYVDv/mXb6FrKZwe4urj+HVm0JvirWv02vz 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 laVbim1eLMqqBb+81P3nZVyNs8S+rU1viFLd7TfTaTZfLPO/3q7Wxeb2720pdu/e 7+/urcFgOAqj8dcvvvn2u5evvv/hx59e3/z8y6+//f7Hn7ArJpRxx/X8wAapZfxl 3i4v7B+DdjK2WblbiSYZjITuaBzhkLiDKGBk6LGRE4RehEfYD0bY4huGkUNHQ2kd MRZxl3Inws54GA5DdzykvMoF5z4m3mAwpiT0HeqMRwQPIl9qXI8GoTULA8LwwCcu d3gwjnzi+550dCMy8jDhw8rMC6SGYX8wcIYqy9HAj0KXhWNOaDiococ5G/uOT8eU k3DIHDKKXOpFxGGRN8ZRhU0CH/IwHAUj5kt4gRwjbygxjEcj7DC3TtmF/jWk/zkt ZZ7sLyAlm/9KJpcqk+b7KDvwLE7UORAo79lUo/KqKrwush8vlfVlv9ytO2W3LzY3 etr+q4rLMtuKjja6rnZpkk8PyvxfUEsDBBQAAAAIALILeTSZ6giZIgcAABgWAAAF AAAAbWQ1LmStmFtv4zYWx58TIN+BmIfCbo0pL4e3BvNgW/Z2e9lLZ+9BFqBEKnY3 sbOW3HFm2v3sK5GU6bghsMAmSCDxSH+Kv3OLqIet3d87tDLN6u2D5ddXl+uHx+2u HSzQWa4uq3vTNOh7y4v1nWta9FV3DuH86vLT1eVFu1o3o/16097ALdqZD2P0CTX7 R7cb9YNr9MvV5S/PJvq6mz5M05+FSdL8d64NZ6NxZ++vXexcu99t0MZ9SOsYVdtN 6w7tuFvkhZ//cbdtXdU6+1VnaVrTrivkNvsH5Od4Twh6h5CchAHtBoTGAesHwxXo BjReoV7D46DXIB0HXgNx4DU4DJjXxCvMP4fEgdeIOPAaFgbgNfEKeE2cDbwmrgC8 hvTAPjQXP23XFrU7s2nq7e5htC+fWndzi9abx3179F4fGmQm5aSa2OvBcEPELTqE WS7u12177xYbuzYbRkdePjl4z170f6Z7bHT3Db715vLERIKpOjHRYLInJnZ7nO/L z9EP2/3GIoI+/7I31PXITFA5QdUE2Qk63CB8O0FdyCYIH6wUxoBUXSp1whNJd+dR 1UmIl9Be4lQlS8lFkNAkCfMHVSehXsJ6CQWKJbZlkLAkOa7KeAnzEuglFSlt5ZwL EsiyQGKpuaxwbeog4VkWnlg6clkJaoJEZFlEYjGKYRCEBYnMssjEUlsQmmMSJCrL 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 AABtZDUuZFBLBQYAAAAACgAKAA0CAAD6bwAAAAA= ------------0HfOWIEbrFHHiydfw9h323--
Mar 27 2006
parent kris <foo bar.com> writes:
Regan Heath wrote:
 On Thu, 23 Mar 2006 16:20:02 -0800, kris <foo bar.com> wrote:
 
 That all sounds great (though I'll admit to being more than a bit 
 leery  of D mixins). I'll take a look at the license, and get back to 
 you via  the Deimos forum?

I just went ahead and converted my hashing code from the struct+mixin approach to a class+factory approach. The source included in the attached zip file hash.zip is public domain, this includes: base.d factory.d md2.d md4.d md5.d sha0.d sha1.d sha256.d sha512.d tiger.d I would very much like to see my code appear in any library that needs/wants it. It'd be nice to get a mention somewhere too, y'know for my ego n'all. Regan

Nice! It's now got a home in mango.crypto.* - Kris
Mar 27 2006
prev sibling parent Kyle Furlong <kylefurlong gmail.com> writes:
kris wrote:
 Sean Kelly wrote:
 Regan Heath wrote:

 You might be interested in some existing crypto work I've done:
   http://svn.dsource.org/projects/deimos/trunk/etc/crypto/hash/

 The library "deimos" never really got off the ground, I think it may 
 be tome to salvage what can be salvaged from deimos and put it 
 somewhere else, perhaps in "Ares", Shaun? If the crypto stuff is 
 unsuitable for any reason let me know and I can re-work it.

That's a bit past the level of what I've been focusing on, but it's certainly a candidate for eventual inclusion. Sean

I've seriously considered adding a crypto package to Mango; particularly in support of network-oriented apps (MD4, MD5, SHA1, some SSL support, and so on). Perhaps that might be a reasonable home for the time being? Should only need support for void[], right?

As I foresee the eventual oneness of Ares + Mango, sure.
Mar 23 2006