|
View:
New views
2 Messages
—
Rating Filter:
Alert me
|
|
|
|
|
|
Re: [erlang-questions] blowfish ECB implementation in erlang?On Sun, Sep 27, 2009 at 11:35 PM, Paul Oliver <puzza007@...> wrote:
Hi, I've rounded out the patch to include the rest of the blowfish functions from openssl and included a primitive test program. Cheers, Paul. [blowfish_ecb_cbc_ofb.patch] diff --git a/lib/crypto/c_src/crypto_drv.c b/lib/crypto/c_src/crypto_drv.c index a5b301f..9d99591 100644 --- a/lib/crypto/c_src/crypto_drv.c +++ b/lib/crypto/c_src/crypto_drv.c @@ -212,6 +212,11 @@ static ErlDrvEntry crypto_driver_entry = { #define DRV_BF_CFB64_ENCRYPT 59 #define DRV_BF_CFB64_DECRYPT 60 +#define DRV_BF_ECB_ENCRYPT 61 +#define DRV_BF_ECB_DECRYPT 62 +#define DRV_BF_OFB64_ENCRYPT 63 +#define DRV_BF_CBC_ENCRYPT 64 +#define DRV_BF_CBC_DECRYPT 65 /* #define DRV_CBC_IDEA_ENCRYPT 34 */ /* #define DRV_CBC_IDEA_DECRYPT 35 */ @@ -507,17 +512,63 @@ static int control(ErlDrvData drv_data, unsigned int command, char *buf, (command == DRV_CBC_DES_ENCRYPT)); return dlen; + case DRV_BF_ECB_ENCRYPT: + case DRV_BF_ECB_DECRYPT: + { + /* buf = klen[4] key data */ + int bf_direction; + const unsigned char *bf_dbuf; /* blowfish input data */ + BF_KEY bf_key; /* blowfish key 8 */ + + klen = get_int32(buf); + key = buf + 4; + bf_dbuf = key + klen; + dlen = len - 4 - klen; + if (dlen < 0) return -1; + BF_set_key(&bf_key, klen, key); + bin = return_binary(rbuf,rlen,dlen); + if (bin==NULL) return -1; + bf_direction = command == DRV_BF_ECB_ENCRYPT ? BF_ENCRYPT : BF_DECRYPT; + BF_ecb_encrypt(bf_dbuf, bin, &bf_key, bf_direction); + return dlen; + } + + case DRV_BF_CBC_ENCRYPT: + case DRV_BF_CBC_DECRYPT: + { + /* buf = klen[4] key ivec[8] data */ + char* ivec; + unsigned char bf_tkey[8]; /* blowfish ivec */ + int bf_direction; + const unsigned char *bf_dbuf; /* blowfish input data */ + BF_KEY bf_key; /* blowfish key 8 */ + + klen = get_int32(buf); + key = buf + 4; + ivec = key + klen; + bf_dbuf = ivec + 8; + dlen = len - 4 - klen - 8; + if (dlen < 0) return -1; + BF_set_key(&bf_key, klen, key); + memcpy(bf_tkey, ivec, 8); + bin = return_binary(rbuf,rlen,dlen); + if (bin==NULL) return -1; + bf_direction = command == DRV_BF_CBC_ENCRYPT ? BF_ENCRYPT : BF_DECRYPT; + BF_cbc_encrypt(bf_dbuf, bin, dlen, &bf_key, bf_tkey, bf_direction); + return dlen; + } + case DRV_BF_CFB64_ENCRYPT: case DRV_BF_CFB64_DECRYPT: { /* buf = klen[4] key ivec[8] data */ char* ivec; - unsigned char bf_tkey[8]; /* blowfish ivec */ - int bf_n; /* blowfish ivec pos */ + unsigned char bf_tkey[8]; /* blowfish ivec */ + int bf_n; /* blowfish ivec pos */ int bf_direction; - const unsigned char *bf_dbuf; /* blowfish input data */ + const unsigned char *bf_dbuf; /* blowfish input data */ BF_KEY bf_key; /* blowfish key 8 */ - + klen = get_int32(buf); key = buf + 4; ivec = key + klen; @@ -534,6 +585,30 @@ static int control(ErlDrvData drv_data, unsigned int command, char *buf, return dlen; } + case DRV_BF_OFB64_ENCRYPT: + { + /* buf = klen[4] key ivec[8] data */ + char* ivec; + unsigned char bf_tkey[8]; /* blowfish ivec */ + int bf_n; /* blowfish ivec pos */ + const unsigned char *bf_dbuf; /* blowfish input data */ + BF_KEY bf_key; /* blowfish key 8 */ + + klen = get_int32(buf); + key = buf + 4; + ivec = key + klen; + bf_dbuf = ivec + 8; + dlen = len - 4 - klen - 8; + if (dlen < 0) return -1; + BF_set_key(&bf_key, klen, key); + memcpy(bf_tkey, ivec, 8); + bin = return_binary(rbuf,rlen,dlen); + if (bin==NULL) return -1; + bf_n = 0; + BF_ofb64_encrypt(bf_dbuf, bin, dlen, &bf_key, bf_tkey, &bf_n); + return dlen; + } + /* case DRV_CBC_IDEA_ENCRYPT: */ /* case DRV_CBC_IDEA_DECRYPT: */ /* buf = key[16] ivec[8] data */ diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml index 7d96017..38dacc0 100644 --- a/lib/crypto/doc/src/crypto.xml +++ b/lib/crypto/doc/src/crypto.xml @@ -337,6 +337,53 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> <c>Key3</c>, and <c>IVec</c> must be 64 bits (8 bytes).</p> </desc> </func> + + <func> + <name>blowfish_ecb_encrypt(Key, Text) -> Cipher</name> + <fsummary>Encrypt the first 64 bits of <c>Text</c> using Blowfish in ECB mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Encrypts the first 64 bits of <c>Text</c> using Blowfish in ECB mode. <c>Key</c> is the Blowfish key. The length of <c>Text</c> must be at least 64 bits (8 bytes).</p> + </desc> + <name>blowfish_ecb_decrypt(Key, Text) -> Cipher</name> + <fsummary>Decrypt the first 64 bits of <c>Text</c> using Blowfish in ECB mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Decrypts the first 64 bits of <c>Text</c> using Blowfish in ECB mode. <c>Key</c> is the Blowfish key. The length of <c>Text</c> must be at least 64 bits (8 bytes).</p> + </desc> + </func> + + <func> + <name>blowfish_cbc_encrypt(Key, Text) -> Cipher</name> + <fsummary>Encrypt <c>Text</c> using Blowfish in CBC mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Encrypts <c>Text</c> using Blowfish in CBC mode. <c>Key</c> is the Blowfish key, and <c>IVec</c> is an + arbitrary initializing vector. The length of <c>IVec</c> + must be 64 bits (8 bytes). The length of <c>Text</c> must be a multiple of 64 bits (8 bytes).</p> + </desc> + <name>blowfish_cbc_decrypt(Key, Text) -> Cipher</name> + <fsummary>Decrypt <c>Text</c> using Blowfish in CBC mode</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Decrypts <c>Text</c> using Blowfish in CBC mode. <c>Key</c> is the Blowfish key, and <c>IVec</c> is an + arbitrary initializing vector. The length of <c>IVec</c> + must be 64 bits (8 bytes). The length of <c>Text</c> must be a multiple 64 bits (8 bytes).</p> + </desc> + </func> + <func> <name>blowfish_cfb64_encrypt(Key, IVec, Text) -> Cipher</name> <fsummary>Encrypt <c>Text</c>using Blowfish in CFB mode with 64 @@ -367,6 +414,23 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]> must be 64 bits (8 bytes).</p> </desc> </func> + + <func> + <name>blowfish_ofb64_encrypt(Key, IVec, Text) -> Cipher</name> + <fsummary>Encrypt <c>Text</c>using Blowfish in OFB mode with 64 + bit feedback</fsummary> + <type> + <v>Key = Text = iolist() | binary()</v> + <v>IVec = Cipher = binary()</v> + </type> + <desc> + <p>Encrypts <c>Text</c> using Blowfish in OFB mode with 64 bit + feedback. <c>Key</c> is the Blowfish key, and <c>IVec</c> is an + arbitrary initializing vector. The length of <c>IVec</c> + must be 64 bits (8 bytes).</p> + </desc> + </func> + <func> <name>aes_cfb_128_encrypt(Key, IVec, Text) -> Cipher</name> <name>aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher</name> diff --git a/lib/crypto/src/crypto.erl b/lib/crypto/src/crypto.erl index 5189677..fa33bad 100644 --- a/lib/crypto/src/crypto.erl +++ b/lib/crypto/src/crypto.erl @@ -30,7 +30,10 @@ -export([md5_mac/2, md5_mac_96/2, sha_mac/2, sha_mac_96/2]). -export([des_cbc_encrypt/3, des_cbc_decrypt/3, des_cbc_ivec/1]). -export([des3_cbc_encrypt/5, des3_cbc_decrypt/5]). --export([blowfish_cfb64_encrypt/3,blowfish_cfb64_decrypt/3]). +-export([blowfish_ecb_encrypt/2, blowfish_ecb_decrypt/2]). +-export([blowfish_cbc_encrypt/3, blowfish_cbc_decrypt/3]). +-export([blowfish_cfb64_encrypt/3, blowfish_cfb64_decrypt/3]). +-export([blowfish_ofb64_encrypt/3]). -export([des_ede3_cbc_encrypt/5, des_ede3_cbc_decrypt/5]). -export([aes_cfb_128_encrypt/3, aes_cfb_128_decrypt/3]). -export([exor/2]). @@ -115,6 +118,11 @@ -define(BF_CFB64_ENCRYPT, 59). -define(BF_CFB64_DECRYPT, 60). +-define(BF_ECB_ENCRYPT, 61). +-define(BF_ECB_DECRYPT, 62). +-define(BF_OFB64_ENCRYPT, 63). +-define(BF_CBC_ENCRYPT, 64). +-define(BF_CBC_DECRYPT, 65). %% -define(IDEA_CBC_ENCRYPT, 34). %% -define(IDEA_CBC_DECRYPT, 35). @@ -303,12 +311,27 @@ des_ede3_cbc_decrypt(Key1, Key2, Key3, IVec, Data) -> %% %% Blowfish %% +blowfish_ecb_encrypt(Key, Data) when byte_size(Data) >= 8 -> + control_bin(?BF_ECB_ENCRYPT, Key, list_to_binary([Data])). + +blowfish_ecb_decrypt(Key, Data) when byte_size(Data) >= 8 -> + control_bin(?BF_ECB_DECRYPT, Key, list_to_binary([Data])). + +blowfish_cbc_encrypt(Key, IVec, Data) when byte_size(Data) rem 8 =:= 0 -> + control_bin(?BF_CBC_ENCRYPT, Key, list_to_binary([IVec, Data])). + +blowfish_cbc_decrypt(Key, IVec, Data) when byte_size(Data) rem 8 =:= 0 -> + control_bin(?BF_CBC_DECRYPT, Key, list_to_binary([IVec, Data])). + blowfish_cfb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> control_bin(?BF_CFB64_ENCRYPT, Key, list_to_binary([IVec, Data])). blowfish_cfb64_decrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> control_bin(?BF_CFB64_DECRYPT, Key, list_to_binary([IVec, Data])). +blowfish_ofb64_encrypt(Key, IVec, Data) when byte_size(IVec) =:= 8 -> + control_bin(?BF_OFB64_ENCRYPT, Key, list_to_binary([IVec, Data])). + %% %% AES in cipher feedback mode (CFB) %% [bf_test.erl] -module(bf_test). -include_lib("eunit/include/eunit.hrl"). -define(KEY, to_bin("0123456789ABCDEFF0E1D2C3B4A59687")). -define(IVEC, to_bin("FEDCBA9876543210")). %% "7654321 Now is the time for " (includes trailing '\0') -define(DATA, to_bin("37363534333231204E6F77206973207468652074696D6520666F722000")). -define(DATA_PADDED, to_bin("37363534333231204E6F77206973207468652074696D6520666F722000000000")). ecb_test(KeyBytes, ClearBytes, CipherBytes) -> crypto:start(), {Key, Clear, Cipher} = {to_bin(KeyBytes), to_bin(ClearBytes), to_bin(CipherBytes)}, crypto:blowfish_ecb_encrypt(Key, Clear) =:= Cipher. ecb_1_test() -> ?assert(ecb_test("0000000000000000", "0000000000000000", "4EF997456198DD78")). ecb_2_test() -> ?assert(ecb_test("FFFFFFFFFFFFFFFF", "FFFFFFFFFFFFFFFF", "51866FD5B85ECB8A")). ecb_3_test() -> ?assert(ecb_test("3000000000000000", "1000000000000001", "7D856F9A613063F2")). ecb_4_test() -> ?assert(ecb_test("1111111111111111", "1111111111111111", "2466DD878B963C9D")). ecb_5_test() -> ?assert(ecb_test("0123456789ABCDEF", "1111111111111111", "61F9C3802281B096")). ecb_6_test() -> ?assert(ecb_test("1111111111111111", "0123456789ABCDEF", "7D0CC630AFDA1EC7")). ecb_7_test() -> ?assert(ecb_test("0000000000000000", "0000000000000000", "4EF997456198DD78")). ecb_8_test() -> ?assert(ecb_test("FEDCBA9876543210", "0123456789ABCDEF", "0ACEAB0FC6A0A28D")). ecb_9_test() -> ?assert(ecb_test("7CA110454A1A6E57", "01A1D6D039776742", "59C68245EB05282B")). ecb_10_test() -> ?assert(ecb_test("0131D9619DC1376E", "5CD54CA83DEF57DA", "B1B8CC0B250F09A0")). ecb_11_test() -> ?assert(ecb_test("07A1133E4A0B2686", "0248D43806F67172", "1730E5778BEA1DA4")). ecb_12_test() -> ?assert(ecb_test("3849674C2602319E", "51454B582DDF440A", "A25E7856CF2651EB")). ecb_13_test() -> ?assert(ecb_test("04B915BA43FEB5B6", "42FD443059577FA2", "353882B109CE8F1A")). ecb_14_test() -> ?assert(ecb_test("0113B970FD34F2CE", "059B5E0851CF143A", "48F4D0884C379918")). ecb_15_test() -> ?assert(ecb_test("0170F175468FB5E6", "0756D8E0774761D2", "432193B78951FC98")). ecb_16_test() -> ?assert(ecb_test("43297FAD38E373FE", "762514B829BF486A", "13F04154D69D1AE5")). ecb_17_test() -> ?assert(ecb_test("07A7137045DA2A16", "3BDD119049372802", "2EEDDA93FFD39C79")). ecb_18_test() -> ?assert(ecb_test("04689104C2FD3B2F", "26955F6835AF609A", "D887E0393C2DA6E3")). ecb_19_test() -> ?assert(ecb_test("37D06BB516CB7546", "164D5E404F275232", "5F99D04F5B163969")). ecb_20_test() -> ?assert(ecb_test("1F08260D1AC2465E", "6B056E18759F5CCA", "4A057A3B24D3977B")). ecb_21_test() -> ?assert(ecb_test("584023641ABA6176", "004BD6EF09176062", "452031C1E4FADA8E")). ecb_22_test() -> ?assert(ecb_test("025816164629B007", "480D39006EE762F2", "7555AE39F59B87BD")). ecb_23_test() -> ?assert(ecb_test("49793EBC79B3258F", "437540C8698F3CFA", "53C55F9CB49FC019")). ecb_24_test() -> ?assert(ecb_test("4FB05E1515AB73A7", "072D43A077075292", "7A8E7BFA937E89A3")). ecb_25_test() -> ?assert(ecb_test("49E95D6D4CA229BF", "02FE55778117F12A", "CF9C5D7A4986ADB5")). ecb_26_test() -> ?assert(ecb_test("018310DC409B26D6", "1D9D5C5018F728C2", "D1ABB290658BC778")). ecb_27_test() -> ?assert(ecb_test("1C587F1C13924FEF", "305532286D6F295A", "55CB3774D13EF201")). ecb_28_test() -> ?assert(ecb_test("0101010101010101", "0123456789ABCDEF", "FA34EC4847B268B2")). ecb_29_test() -> ?assert(ecb_test("1F1F1F1F0E0E0E0E", "0123456789ABCDEF", "A790795108EA3CAE")). ecb_30_test() -> ?assert(ecb_test("E0FEE0FEF1FEF1FE", "0123456789ABCDEF", "C39E072D9FAC631D")). ecb_31_test() -> ?assert(ecb_test("0000000000000000", "FFFFFFFFFFFFFFFF", "014933E0CDAFF6E4")). ecb_32_test() -> ?assert(ecb_test("FFFFFFFFFFFFFFFF", "0000000000000000", "F21E9A77B71C49BC")). ecb_33_test() -> ?assert(ecb_test("0123456789ABCDEF", "0000000000000000", "245946885754369A")). ecb_34_test() -> ?assert(ecb_test("FEDCBA9876543210", "FFFFFFFFFFFFFFFF", "6B5C5A9C5D9E0A5A")). %% Chaining mode tests cbc_test() -> crypto:start(), ?assert(crypto:blowfish_cbc_encrypt(?KEY, ?IVEC, ?DATA_PADDED) =:= to_bin("6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC")). cfb64_test() -> crypto:start(), ?assert(crypto:blowfish_cfb64_encrypt(?KEY, ?IVEC, ?DATA) =:= to_bin("E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3")). ofb64_test() -> crypto:start(), ?assert(crypto:blowfish_ofb64_encrypt(?KEY, ?IVEC, ?DATA) =:= to_bin("E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA")). %% @spec to_bin(string()) -> binary() %% @doc Convert a hexadecimal string to a binary. to_bin(L) -> to_bin(L, []). %% @spec dehex(char()) -> integer() %% @doc Convert a hex digit to its integer value. dehex(C) when C >= $0, C =< $9 -> C - $0; dehex(C) when C >= $a, C =< $f -> C - $a + 10; dehex(C) when C >= $A, C =< $F -> C - $A + 10. to_bin([], Acc) -> iolist_to_binary(lists:reverse(Acc)); to_bin([C1, C2 | Rest], Acc) -> to_bin(Rest, [(dehex(C1) bsl 4) bor dehex(C2) | Acc]). ________________________________________________________________ erlang-patches mailing list. See http://www.erlang.org/faq.html erlang-patches (at) erlang.org |
| Free embeddable forum powered by Nabble | Forum Help |