crypto
Crypto Functions
This module provides a set of cryptographic functions.
References:
-
md5: The MD5 Message Digest Algorithm (RFC 1321)
-
sha: Secure Hash Standard (FIPS 180-2)
-
hmac: Keyed-Hashing for Message Authentication (RFC 2104)
-
des: Data Encryption Standard (FIPS 46-3)
-
aes: Advanced Encryption Standard (AES) (FIPS 197)
-
ecb, cbc, cfb, ofb: Recommendation for Block Cipher Modes of Operation (NIST SP 800-38A).
-
rsa: Recommendation for Block Cipher Modes of Operation (NIST 800-38A)
-
dss: Digital Signature Standard (FIPS 186-2)
The above publications can be found at
Types
byte() = 0 ... 255 ioelem() = byte() | binary() | iolist() iolist() = [ioelem()] Mpint() = <<ByteLen:32/integer-big, Bytes:ByteLen/binary>>
Functions
start() -> ok
Starts the crypto server.
stop() -> ok
Stops the crypto server.
info() -> [atom()]
Provides the available crypto functions in terms of a list of atoms.
info_lib() -> [{Name,VerNum,VerStr}]
Name = binary()
VerNum = integer()
VerStr = binary()
Provides the name and version of the libraries used by crypto.
Name
is the name of the library. VerNum
is
the numeric version according to the library's own versioning
scheme. VerStr
contains a text variant of the version.
> info_lib().
[{<<"OpenSSL">>,9469983,<<"OpenSSL 0.9.8a 11 Oct 2005">>}]
md5(Data) -> Digest
Data = iolist() | binary()
Digest = binary()
Computes an MD5
message digest from Data
, where
the length of the digest is 128 bits (16 bytes).
md5_init() -> Context
Context = binary()
Creates an MD5 context, to be used in subsequent calls to
md5_update/2
.
md5_update(Context, Data) -> NewContext
Data = iolist() | binary()
Context = NewContext = binary()
Updates an MD5 Context
with Data
, and returns
a NewContext
.
md5_final(Context) -> Digest
Context = Digest = binary()
Finishes the update of an MD5 Context
and returns
the computed MD5
message digest.
sha(Data) -> Digest
Data = iolist() | binary()
Digest = binary()
Computes an SHA
message digest from Data
, where
the length of the digest is 160 bits (20 bytes).
sha_init() -> Context
Context = binary()
Creates an SHA context, to be used in subsequent calls to
sha_update/2
.
sha_update(Context, Data) -> NewContext
Data = iolist() | binary()
Context = NewContext = binary()
Updates an SHA Context
with Data
, and returns
a NewContext
.
sha_final(Context) -> Digest
Context = Digest = binary()
Finishes the update of an SHA Context
and returns
the computed SHA
message digest.
md5_mac(Key, Data) -> Mac
Key = Data = iolist() | binary()
Mac = binary()
Computes an MD5 MAC
message authentification code
from Key
and Data
, where the the length of the
Mac is 128 bits (16 bytes).
md5_mac_96(Key, Data) -> Mac
Key = Data = iolist() | binary()
Mac = binary()
Computes an MD5 MAC
message authentification code
from Key
and Data
, where the length of the Mac
is 96 bits (12 bytes).
sha_mac(Key, Data) -> Mac
Key = Data = iolist() | binary()
Mac = binary()
Computes an SHA MAC
message authentification code
from Key
and Data
, where the length of the Mac
is 160 bits (20 bytes).
sha_mac_96(Key, Data) -> Mac
Key = Data = iolist() | binary()
Mac = binary()
Computes an SHA MAC
message authentification code
from Key
and Data
, where the length of the Mac
is 96 bits (12 bytes).
des_cbc_encrypt(Key, IVec, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Encrypts Text
according to DES in CBC
mode. Text
must be a multiple of 64 bits (8
bytes). Key
is the DES key, and IVec
is an
arbitrary initializing vector. The lengths of Key
and
IVec
must be 64 bits (8 bytes).
des_cbc_decrypt(Key, IVec, Cipher) -> Text
Key = Cipher = iolist() | binary()
IVec = Text = binary()
Decrypts Cipher
according to DES in CBC mode.
Key
is the DES key, and IVec
is an arbitrary
initializing vector. Key
and IVec
must have
the same values as those used when encrypting. Cipher
must be a multiple of 64 bits (8 bytes). The lengths of
Key
and IVec
must be 64 bits (8 bytes).
des_cbc_ivec(Data) -> IVec
Data = iolist() | binary()
IVec = binary()
Returns the IVec
to be used in a next iteration of
des_cbc_[encrypt|decrypt]
. Data
is the encrypted
data from the previous iteration step.
des3_cbc_encrypt(Key1, Key2, Key3, IVec, Text) -> Cipher
Key1 =Key2 = Key3 Text = iolist() | binary()
IVec = Cipher = binary()
Encrypts Text
according to DES3 in CBC
mode. Text
must be a multiple of 64 bits (8
bytes). Key1
, Key2
, Key3
, are the DES
keys, and IVec
is an arbitrary initializing
vector. The lengths of each of Key1
, Key2
,
Key3
and IVec
must be 64 bits (8 bytes).
des3_cbc_decrypt(Key1, Key2, Key3, IVec, Cipher) -> Text
Key1 = Key2 = Key3 = Cipher = iolist() | binary()
IVec = Text = binary()
Decrypts Cipher
according to DES3 in CBC mode.
Key1
, Key2
, Key3
are the DES key, and
IVec
is an arbitrary initializing vector.
Key1
, Key2
, Key3
and IVec
must
and IVec
must have the same values as those used when
encrypting. Cipher
must be a multiple of 64 bits (8
bytes). The lengths of Key1
, Key2
,
Key3
, and IVec
must be 64 bits (8 bytes).
blowfish_ecb_encrypt(Key, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Encrypts the first 64 bits of Text
using Blowfish in ECB mode. Key
is the Blowfish key. The length of Text
must be at least 64 bits (8 bytes).
blowfish_ecb_decrypt(Key, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Decrypts the first 64 bits of Text
using Blowfish in ECB mode. Key
is the Blowfish key. The length of Text
must be at least 64 bits (8 bytes).
blowfish_cbc_encrypt(Key, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Encrypts Text
using Blowfish in CBC mode. Key
is the Blowfish key, and IVec
is an
arbitrary initializing vector. The length of IVec
must be 64 bits (8 bytes). The length of Text
must be a multiple of 64 bits (8 bytes).
blowfish_cbc_decrypt(Key, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Decrypts Text
using Blowfish in CBC mode. Key
is the Blowfish key, and IVec
is an
arbitrary initializing vector. The length of IVec
must be 64 bits (8 bytes). The length of Text
must be a multiple 64 bits (8 bytes).
blowfish_cfb64_encrypt(Key, IVec, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Encrypts Text
using Blowfish in CFB mode with 64 bit
feedback. Key
is the Blowfish key, and IVec
is an
arbitrary initializing vector. The length of IVec
must be 64 bits (8 bytes).
blowfish_cfb64_decrypt(Key, IVec, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Decrypts Text
using Blowfish in CFB mode with 64 bit
feedback. Key
is the Blowfish key, and IVec
is an
arbitrary initializing vector. The length of IVec
must be 64 bits (8 bytes).
blowfish_ofb64_encrypt(Key, IVec, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Encrypts Text
using Blowfish in OFB mode with 64 bit
feedback. Key
is the Blowfish key, and IVec
is an
arbitrary initializing vector. The length of IVec
must be 64 bits (8 bytes).
aes_cfb_128_encrypt(Key, IVec, Text) -> Cipher
aes_cbc_128_encrypt(Key, IVec, Text) -> Cipher
Key = Text = iolist() | binary()
IVec = Cipher = binary()
Encrypts Text
according to AES in Cipher Feedback
mode (CFB) or Cipher Block Chaining mode (CBC). Text
must be a multiple of 128 bits (16 bytes). Key
is the
AES key, and IVec
is an arbitrary initializing vector.
The lengths of Key
and IVec
must be 128 bits
(16 bytes).
aes_cfb_128_decrypt(Key, IVec, Cipher) -> Text
aes_cbc_128_decrypt(Key, IVec, Cipher) -> Text
Key = Cipher = iolist() | binary()
IVec = Text = binary()
Decrypts Cipher
according to Cipher Feedback Mode (CFB)
or Cipher Block Chaining mode (CBC).
Key
is the AES key, and IVec
is an arbitrary
initializing vector. Key
and IVec
must have
the same values as those used when encrypting. Cipher
must be a multiple of 128 bits (16 bytes). The lengths of
Key
and IVec
must be 128 bits (16 bytes).
aes_cbc_ivec(Data) -> IVec
Data = iolist() | binary()
IVec = binary()
Returns the IVec
to be used in a next iteration of
aes_cbc_*_[encrypt|decrypt]
. Data
is the encrypted
data from the previous iteration step.
erlint(Mpint) -> N
mpint(N) -> Mpint
Mpint = binary()
N = integer()
Convert a binary multi-precision integer Mpint
to and from
an erlang big integer. A multi-precision integer is a binary
with the following form:
<<ByteLen:32/integer, Bytes:ByteLen/binary>>
where both
ByteLen
and Bytes
are big-endian. Mpints are used in
some of the functions in crypto
and are not translated
in the API for performance reasons.
rand_bytes(N) -> binary()
N = integer()
Generates N bytes randomly uniform 0..255, and returns the
result in a binary. Uses the crypto
library pseudo-random
number generator.
rand_uniform(Lo, Hi) -> N
Lo, Hi, N = Mpint | integer()
Mpint = binary()
Generate a random number N, Lo =< N < Hi.
Uses the
crypto
library pseudo-random number generator. The
arguments (and result) can be either erlang integers or binary
multi-precision integers.
mod_exp(N, P, M) -> Result
N, P, M, Result = Mpint
Mpint = binary()
This function performs the exponentiation N ^ P mod M
,
using the crypto
library.
rsa_sign(Data, Key) -> Signature
rsa_sign(DigestType, Data, Key) -> Signature
Data = Mpint
Key = [E, N, D]
E, N, D = Mpint
DigestType = md5 | sha
Mpint = binary()
Signature = binary()
E
is the public exponent, N
is public modulus and
D
is the private exponent.DigestType
is sha.Calculates a DigestType
digest of the Data
and creates a RSA signature with the private key Key
of the digest.
rsa_verify(Data, Signature, Key) -> Verified
rsa_verify(DigestType, Data, Signature, Key) -> Verified
Verified = boolean()
Data, Signature = Mpint
Key = [E, N]
E, N = Mpint
DigestType = md5 | sha
Mpint = binary()
E
is the public exponent and N
is public modulus.DigestType
is sha.Calculates a DigestType
digest of the Data
and verifies that the digest matches the RSA signature using the
signer's public key Key
.
rsa_public_encrypt(PlainText, PublicKey, Padding) -> ChipherText
PlainText = binary()
PublicKey = [E, N]
E, N = Mpint
Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding
ChipherText = binary()
E
is the public exponent and N
is public modulus.Encrypts the PlainText
(usually a session key) using the PublicKey
and returns the cipher. The Padding
decides what padding mode is used,
rsa_pkcs1_padding
is PKCS #1 v1.5 currently the most
used mode and rsa_pkcs1_oaep_padding
is EME-OAEP as
defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty encoding
parameter. This mode is recommended for all new applications.
The size of the Msg
must be less
than byte_size(N)-11
if
rsa_pkcs1_padding
is used, byte_size(N)-41
if
rsa_pkcs1_oaep_padding
is used and byte_size(N)
if rsa_no_padding
is used.
Where byte_size(N) is the size part of an Mpint-1
.
rsa_private_decrypt(ChipherText, PrivateKey, Padding) -> PlainText
ChipherText = binary()
PrivateKey = [E, N, D]
E, N, D = Mpint
Padding = rsa_pkcs1_padding | rsa_pkcs1_oaep_padding | rsa_no_padding
PlainText = binary()
E
is the public exponent, N
is public modulus and
D
is the private exponent.Decrypts the ChipherText
(usually a session key encrypted with
rsa_public_encrypt/3)
using the PrivateKey
and returns the
message. The Padding
is the padding mode that was
used to encrypt the data,
see rsa_public_encrypt/3.
rsa_private_encrypt(PlainText, PrivateKey, Padding) -> ChipherText
PlainText = binary()
PrivateKey = [E, N, D]
E, N, D = Mpint
Padding = rsa_pkcs1_padding | rsa_no_padding
ChipherText = binary()
E
is the public exponent, N
is public modulus and
D
is the private exponent.Encrypts the PlainText
using the PrivateKey
and returns the cipher. The Padding
decides what padding mode is used,
rsa_pkcs1_padding
is PKCS #1 v1.5 currently the most
used mode.
The size of the Msg
must be less than byte_size(N)-11
if
rsa_pkcs1_padding
is used, and byte_size(N)
if rsa_no_padding
is used. Where byte_size(N) is the size part of an Mpint-1
.
rsa_public_decrypt(ChipherText, PublicKey, Padding) -> PlainText
ChipherText = binary()
PublicKey = [E, N]
E, N = Mpint
Padding = rsa_pkcs1_padding | rsa_no_padding
PlainText = binary()
E
is the public exponent and N
is public modulusDecrypts the ChipherText
(encrypted with
rsa_private_encrypt/3)
using the PrivateKey
and returns the
message. The Padding
is the padding mode that was
used to encrypt the data,
see rsa_private_encrypt/3.
dss_sign(Data, Key) -> Signature
Digest = Mpint
Key = [P, Q, G, X]
P, Q, G, X = Mpint
Mpint = binary()
Signature = binary()
P
, Q
and G
are the dss
parameters and X
is the private key.Calculates the sha digest of the Data
and creates a DSS signature with the private key Key
of the digest.
dss_verify(Data, Signature, Key) -> Verified
Verified = boolean()
Digest, Signature = Mpint
Key = [P, Q, G, Y]
P, Q, G, Y = Mpint
Mpint = binary()
P
, Q
and G
are the dss
parameters and Y
is the public key.Calculates the sha digest of the Data
and verifies that the
digest matches the DSS signature using the public key Key
.
rc4_encrypt(Key, Data) -> Result
Key, Data = iolist() | binary()
Result = binary()
Encrypts the data with RC4 symmetric stream encryption. Since it is symmetric, the same function is used for decryption.
dh_generate_key(DHParams) -> {PublicKey,PrivateKey}
dh_generate_key(PrivateKey, DHParams) -> {PublicKey,PrivateKey}
DHParameters = [P, G]
P, G = Mpint
PublicKey, PrivateKey = Mpint()
P
is the shared prime number and G
is the shared generator.Generates a Diffie-Hellman PublicKey
and PrivateKey
(if not given).
dh_compute_key(OthersPublicKey, MyPrivateKey, DHParams) -> SharedSecret
DHParameters = [P, G]
P, G = Mpint
OthersPublicKey, MyPrivateKey = Mpint()
SharedSecret = binary()
P
is the shared prime number and G
is the shared generator.Computes the shared secret from the private key and the other party's public key.
exor(Data1, Data2) -> Result
Data1, Data2 = iolist() | binary()
Result = binary()
Performs bit-wise XOR (exclusive or) on the data supplied.
DES in CBC mode
The Data Encryption Standard (DES) defines an algorithm for encrypting and decrypting an 8 byte quantity using an 8 byte key (actually only 56 bits of the key is used).
When it comes to encrypting and decrypting blocks that are multiples of 8 bytes various modes are defined (NIST SP 800-38A). One of those modes is the Cipher Block Chaining (CBC) mode, where the encryption of an 8 byte segment depend not only of the contents of the segment itself, but also on the result of encrypting the previous segment: the encryption of the previous segment becomes the initializing vector of the encryption of the current segment.
Thus the encryption of every segment depends on the encryption key (which is secret) and the encryption of the previous segment, except the first segment which has to be provided with an initial initializing vector. That vector could be chosen at random, or be a counter of some kind. It does not have to be secret.
The following example is drawn from the old FIPS 81 standard (replaced by NIST SP 800-38A), where both the plain text and the resulting cipher text is settled. The following code fragment returns `true'.
Key = <<16#01,16#23,16#45,16#67,16#89,16#ab,16#cd,16#ef>>, IVec = <<16#12,16#34,16#56,16#78,16#90,16#ab,16#cd,16#ef>>, P = "Now is the time for all ", C = crypto:des_cbc_encrypt(Key, IVec, P), % Which is the same as P1 = "Now is t", P2 = "he time ", P3 = "for all ", C1 = crypto:des_cbc_encrypt(Key, IVec, P1), C2 = crypto:des_cbc_encrypt(Key, C1, P2), C3 = crypto:des_cbc_encrypt(Key, C2, P3), C = <<C1/binary, C2/binary, C3/binary>>, C = <<16#e5,16#c7,16#cd,16#de,16#87,16#2b,16#f2,16#7c, 16#43,16#e9,16#34,16#00,16#8c,16#38,16#9c,16#0f, 16#68,16#37,16#88,16#49,16#9a,16#7c,16#05,16#f6>>, <<"Now is the time for all ">> == crypto:des_cbc_decrypt(Key, IVec, C).
The following is true for the DES CBC mode. For all
decompositions P1 ++ P2 = P
of a plain text message
P
(where the length of all quantities are multiples of 8
bytes), the encryption C
of P
is equal to C1 ++
C2
, where C1
is obtained by encrypting P1
with
Key
and the initializing vector IVec
, and where
C2
is obtained by encrypting P2
with Key
and the initializing vector last8(C1)
,
where last(Binary)
denotes the last 8 bytes of the
binary Binary
.
Similarly, for all decompositions C1 ++ C2 = C
of a
cipher text message C
(where the length of all quantities
are multiples of 8 bytes), the decryption P
of C
is equal to P1 ++ P2
, where P1
is obtained by
decrypting C1
with Key
and the initializing vector
IVec
, and where P2
is obtained by decrypting
C2
with Key
and the initializing vector
last8(C1)
, where last8(Binary)
is as above.
For DES3 (which uses three 64 bit keys) the situation is the same.
- start/0
- stop/0
- info/0
- info_lib/0
- md5/1
- md5_init/0
- md5_update/2
- md5_final/1
- sha/1
- sha_init/0
- sha_update/2
- sha_final/1
- md5_mac/2
- md5_mac_96/2
- sha_mac/2
- sha_mac_96/2
- des_cbc_encrypt/3
- des_cbc_decrypt/3
- des_cbc_ivec/1
- des3_cbc_encrypt/5
- des3_cbc_decrypt/5
- blowfish_ecb_encrypt/2
- blowfish_ecb_decrypt/2
- blowfish_cbc_encrypt/2
- blowfish_cbc_decrypt/2
- blowfish_cfb64_encrypt/3
- blowfish_cfb64_decrypt/3
- blowfish_ofb64_encrypt/3
- aes_cfb_128_encrypt/3
- aes_cbc_128_encrypt/3
- aes_cfb_128_decrypt/3
- aes_cbc_128_decrypt/3
- aes_cbc_ivec/1
- erlint/1
- mpint/1
- rand_bytes/1
- rand_uniform/2
- mod_exp/3
- rsa_sign/2
- rsa_sign/3
- rsa_verify/3
- rsa_verify/4
- rsa_public_encrypt/3
- rsa_private_decrypt/3
- rsa_private_encrypt/3
- rsa_public_decrypt/3
- dss_sign/2
- dss_verify/3
- rc4_encrypt/2
- dh_generate_key/1
- dh_generate_key/2
- dh_compute_key/3
- exor/2