# Crypto Module

% this function will return each supported algorithms
% in list [{hashs, _}, {ciphers, _}, {public_keys, _}]
crypto:support().

% this function will return all available exported 
% APIs function
crypto:info().

% will return used library and systems 
crypto:info_lib().

% will return version library
crypto:version().

% generate random bytes
crypto:rand_bytes(32).

% xor two iolist and return result
crypto:exor(<<"test">>, <<"test">>).
% return <<0,0,0,0>>
crypto:exor(<<"random">>, <<"toptop">>).
%return crypto:exor(<<"random">>, <<"toptop">>).

% generate big value through nif
% last arguments is the base
% python equivalence:  15**15 % 16
crypto:mod_pow(15, 15, 16).
% return <<15>>

% hash functions are really simple
% note: using this way all funtions are not fully exported
DATA = <<"test">>.
crypto:md5(DATA).
crypto:sha(DATA).
crypto:sha224(DATA).
crypto:sha256(DATA).
crypto:sha512(DATA).

% another method with hash function.
MSG = <<"test">>.
crypto:hash(md5, MSG).
crypto:hash(ripemd160, MSG).
crypto:hash(sha, MSG).
crypto:hash(sha224, MSG).
crypto:hash(sha256, MSG).
crypto:hash(sha384, MSG).
crypto:hash(sha512, MSG).

KEY=<<"thisisyourkey">>.
DATA=<<"thisisyourdata">>.

crypto:hmac(md5, KEY, DATA).
crypto:hmac(sha, KEY, DATA).
crypto:hmac(sha224, KEY, DATA).
crypto:hmac(sha256, KEY, DATA).
crypto:hmac(sha384, KEY, DATA).
crypto:hmac(sha512, KEY, DATA).

% first, we start crypto application (which launch nif crypto)
crypto:start()

% we will try some algorithm for test
% We can create IVs for each cipher with algoname_mode_ivec function
% IVs are fixed length.
DES_CBC_IV = crypto:des_cbc_ivec(crypto:rand_bytes(16)).

% des key is fixed to 56bits + 8bits, so 64bits/8bytes
DES_CBC_KEY = crypto:rand_bytes(8).

% cbc need fixed length, messages need to be equal to 8bytes or
% padded.
DES_CBC_MSG = crypto:rand_bytes(8).

% this return the encrypted message.
DES_CIPHER = crypto:des_cbc_encrypt(DES_CBC_KEY, DES_CBC_IV, DES_CBC_MSG).

% your plaintext need to be padded, or exactly
% measuring 128bits.
PlainText = <<"">>

% one padding method, return a list of bitstring.
MsgPaddingWithList = 
fun P(<<Head:128/bitstring, Tail/bitstring>>, Acc) -> P(Tail, Acc ++ [Head]);
    P(<<Rest/bitstring>>, Acc) -> 
      RestSize = 128 - bit_size(Rest),
      Padding = << <<X:1>> || X <- lists:map(fun(_) -> 0 end, lists:seq(1,RestSize)) >>,
      Acc ++ [<<Rest/bitstring, Padding/bitstring>>]
end.

% another padding method, work directly with bitstring
MsgPaddingWithIfGuards =
fun P(Data) when is_bitstring(Data) -> 
    PaddingSize = 128 - (bit_size(Data) rem 128), 
    if PaddingSize =:= 0 -> 
      Data; 
    true -> 
      Padding = << <<X:1>> || X <- lists:map(fun(_) -> 0 end, lists:seq(1,PaddingSize)) >>, 
      <<Data/bitstring, Padding/bitstring>> 
    end 
end.

% same function with fun pattern matching and list support
MessagePadding = 
fun P(Data) when is_list(Data) -> P(list_to_binary(Data));
    P(Data) when is_bitstring(Data), 
                 bit_size(Data) rem 128 =:= 0 -> Data; 
    P(Data) when is_bitstring(Data), 
                 bit_size(Data) rem 128 =/= 0 ->
      PaddingSize = 128 - (bit_size(Data) rem 128),
      PaddingGen = lists:map(fun(_) -> 0 end, lists:seq(1, PaddingSize)),
      Padding = << <<X:1>> || X <- PaddingGen >>, 
      <<Data/bitstring, Padding/bitstring >>
end.

% remove padding from unencrypted message
MessageRemovePadding = 
fun P(Data) when is_list(Data) -> P(list_to_binary(Data));
    P(Data) when is_bitstring(Data) ->
      << <<X>> || <<X>> <= Data, X =/= 0 >>
end.

% Here your password
Password = <<"ThisIsMyPassword">>.

% aes use a key space of 128bits or 256bits. In this 
% example I will use aes 128. So, if the password is
% too long, we need to shrink it. The best way for doing
% that is to use a hash function.
PasswordHash = crypto:hash(sha512, Password).
<<Key:128/bitstring, _/bitstring>> = PasswordHash.

% IV (initialization vector) is publicly known and
% need to be random.
IV = crypto:rand_bytes(16).

% we can now encrypt with aes128 cbc:
C = crypto:aes_cbc_128_encrypt(Key, IV, MessagePadding(PlainText)).

% Ciphertext could be decrypted with decrypt function:
P = MessageRemovePadding(crypto:aes_cbc_128_decrypt(Key, IV, C)).

KEY=crypto:rand_bytes(16). % key
IV=crypto:rand_bytes(16).  % init vector
AAD=crypto:rand_bytes(16). % authentification data
MSG=crypto:rand_bytes(16). % plain text
crypto:block_encrypt(aes_gcm, KEY, IV, {AAD, MSG}).

# ETF

% encoding
erlang:term_to_binary().

% decoding
erlang:binary_to_term().
/* standard function: printf
 * file descriptor management: fdopen, fclose 
 */
#include <stdio.h>

/* memory management; malloc, free */
#include <stdlib.h>

/* memory sanitize: memset */
#incluse <string.h>

/* main Erlang interface header for
 * encoding, decoding and manage memory with
 * ei_* and ei_x_* functions 
 */
#include "ei.h"
# GNU Makefile
# set erlang path, in /usr/lib/erlang or /usr/local/lib/erlang
ERLANG_PATH ?= /usr/local/lib/erlang/lib
ERLANG_LIBRARY_PATH := $(ERLANG_PATH)/usr
ERLANG_INCLUDE_PATH := $(ERLANG_PATH)/include
ERLANG_LIBRARIES := ei

# include erlang library and headers
CC_ERLANG_PATH := -L${ERLANG_LIBRARY_PATH} -I${ERLANG_INCLUDE_PATH}

# expand all used erlang libraries (ei in our case)
CC_ERLANG_LIBS := $(foreach lib, $(ERLANG_LIBRARIES), -l$(lib))
CC_OPTS := -Wall $(CC_ERLANG_PATH) $(CC_ERLANG_LIBS)
CC := cc

help:
  @echo Usage: make build TARGET=mysource.c

build:
# if TARGET variable is set, build it...
ifdef TARGET
  $(CC) $(CC_OPTS) $(TARGET) $(CC_ERLANG_LIBS)

# else return an error
else
  @echo "please set TARGET parameter
endif
int
main(void) {
  int index = 0;           // buffer index
  char buffer[1024];       // buffer allocated on the stack
  memset(buffer, 0, 1024); // sanitize buffer 
}
int
main(void) {
  int index = 0;           // buffer index
  char buffer[1024];       // buffer allocated on the stack
  memset(buffer, 0, 1024); // sanitize buffer 
}

# httpd

%%% Start
Config = [mod_alias, mod_auth, mod_esi, mod_damn],
inets:start(),
inets:start(httpd, Config).

%%% Info
Pid = proplists:get_value(httpd, httpd:services()),
httpd:service_info(Pid).

%%% Stop
Pid = proplists:get_value(httpd, httpd:services()),
inets:stop(httpd, Pid).

# xmerl

%  Parsing stream in erlang is straightforward, with sax method
ContinuationFun = fun(X) -> 
  io:format("~p~n", [X]) 
end.

EventFun = fun(Event, Location, State) -> 
  io:format("event: ~p~n", [Event]),
  io:format("location: ~p~n", [Location]),
  io:format("state: ~p~n", [State]) 
end.

xmerl_sax_parser:stream(YourStreamHere, [{continuation_fun, ContinuationFun, {event_fun, EventFun}])
% parsing html page
inets:start().
inets:start(httpc, [{profile, httpc}]).
{ok, {_,_,Page} = httpc:request("http://yoururl.com").

ContinuationFun = fun(X) -> 
  io:format("~p~n", [X]) 
end.

EventFun = fun(Event, Location, State) -> 
  io:format("event: ~p~n", [Event]),
  io:format("location: ~p~n", [Location]),
  io:format("state: ~p~n", [State]) 
end.

xmerl_sax_parser:stream(page, [{continuation_fun, ContinuationFun}, {event_fun, EventFun}].

# merl

merl:quote("inc(X, Y) when Y > 0 -> X + Y. t() -> ok.").

returned data:

[{function,1,inc,2,
           [{clause,1,
                    [{var,1,'X'},{var,1,'Y'}],
                    [[{op,1,'>',{var,1,'Y'},{integer,1,0}}]],
                    [{op,1,'+',{var,1,'X'},{var,1,'Y'}}]}]},
 {function,1,t,0,[{clause,1,[],[],[{atom,1,ok}]}]}]
MyCode = "-module(test). -export([t/0]). t () -> ok.".
MyAST = merl:quote(MyCode.)
merl:compile_and_load(MyAST).

test:t().

# network configuration

TODO

  • http://erlang.org/pipermail/erlang-questions/2011-April/057850.html
  • http://erlang.org/faq/how_do_i.html#idp32278352
  • http://erlang.org/doc/man/kernel_app.html
  • http://stackoverflow.com/questions/2369341
  • http://erlang.org/doc/apps/erts/erl_dist_protocol.html

# NIFs

TODO

  1. you need to create two distinct files, C and Erlang file. You can also create Makefile if you want.
  1. Makefile will contain all compile rules