aboutsummaryrefslogtreecommitdiffstats
path: root/lib/public_key/src
diff options
context:
space:
mode:
authorSverker Eriksson <[email protected]>2011-10-24 15:01:28 +0200
committerIngela Anderton Andin <[email protected]>2011-11-01 17:04:20 +0100
commit68e803093b8bf43b39f3090a1b717b850a5e8f4b (patch)
treeae7d93bb4c017578c3a7637ae13b405c09d02e41 /lib/public_key/src
parent1564b5853f286c97a7c9e1d6715d3c6f10bea50f (diff)
downloadotp-68e803093b8bf43b39f3090a1b717b850a5e8f4b.tar.gz
otp-68e803093b8bf43b39f3090a1b717b850a5e8f4b.tar.bz2
otp-68e803093b8bf43b39f3090a1b717b850a5e8f4b.zip
Clean up of public_key code adding specs and documentation
Diffstat (limited to 'lib/public_key/src')
-rw-r--r--lib/public_key/src/pubkey_pbe.erl57
-rw-r--r--lib/public_key/src/pubkey_pem.erl63
-rw-r--r--lib/public_key/src/public_key.erl85
3 files changed, 81 insertions, 124 deletions
diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl
index 32be347039..77d6943d96 100644
--- a/lib/public_key/src/pubkey_pbe.erl
+++ b/lib/public_key/src/pubkey_pbe.erl
@@ -26,7 +26,6 @@
-export([pbdkdf1/4, pbdkdf2/6]).
-define(DEFAULT_SHA_MAC_KEYLEN, 20).
-
-define(ASN1_OCTET_STR_TAG, 4).
-define(IV_LEN, 8).
@@ -34,11 +33,11 @@
%% Internal application API
%%====================================================================
-pbdkdf2(Password, Salt, Count, DerivedKeyLen, Prf, PrfOutputLen)->
- NumBlocks = ceiling(DerivedKeyLen / PrfOutputLen),
- NumLastBlockOctets = DerivedKeyLen - (NumBlocks - 1) * PrfOutputLen ,
- blocks(NumBlocks, NumLastBlockOctets, 1, Password, Salt, Count, Prf, PrfOutputLen, <<>>).
-
+%%--------------------------------------------------------------------
+-spec encode(binary(), string(), string(), term()) -> binary().
+%%
+%% Description: Performs password based encoding
+%%--------------------------------------------------------------------
encode(Data, Password, "DES-CBC" = Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
crypto:des_cbc_encrypt(Key, IV, Data);
@@ -51,7 +50,11 @@ encode(Data, Password, "DES-EDE3-CBC" = Cipher, KeyDevParams) ->
encode(Data, Password, "RC2-CBC" = Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
crypto:rc2_cbc_encrypt(Key, IV, Data).
-
+%%--------------------------------------------------------------------
+-spec decode(binary(), string(), string(), term()) -> binary().
+%%
+%% Description: Performs password based decoding
+%%--------------------------------------------------------------------
decode(Data, Password,"DES-CBC"= Cipher, KeyDevParams) ->
{Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
crypto:des_cbc_decrypt(Key, IV, Data);
@@ -102,7 +105,13 @@ decrypt_parameters(#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-password_to_key_and_iv(Password, Cipher, {salt, Salt}) ->
+password_to_key_and_iv(Password, _, #'PBES2-params'{} = Params) ->
+ {Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen, IV} =
+ key_derivation_params(Params),
+ <<Key:KeyLen/binary, _/binary>> =
+ pbdkdf2(Password, Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen),
+ {Key, IV};
+password_to_key_and_iv(Password, Cipher, Salt) ->
KeyLen = derived_key_length(Cipher, undefined),
<<Key:KeyLen/binary, _/binary>> =
pem_encrypt(<<>>, Password, Salt, ceiling(KeyLen div 16), <<>>, md5),
@@ -110,12 +119,6 @@ password_to_key_and_iv(Password, Cipher, {salt, Salt}) ->
%% pbdkdf1 and uses then salt as IV
{Key, Salt}.
-password_to_key_and_iv(Password, _, #'PBES2-params'{} = Params) ->
- {Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen, IV} =
- key_derivation_params(Params),
- <<Key:KeyLen/binary, _/binary>> =
- pbdkdf2(Password, Salt, ItrCount, KeyLen, PseudoRandomFunction, PseudoOtputLen),
- {Key, IV}.
pem_encrypt(_, _, _, 0, Acc, _) ->
Acc;
pem_encrypt(Prev, Password, Salt, Count, Acc, Hash) ->
@@ -129,8 +132,8 @@ do_pbdkdf1(Prev, Count, Acc, Hash) ->
do_pbdkdf1(Result, Count-1 , <<Result/binary, Acc/binary>>, Hash).
iv(#'PBES2-params_encryptionScheme'{algorithm = Algo,
- parameters = ASNIV}) when (Algo == ?'desCBC') or
- (Algo == ?'des-EDE3-CBC') ->
+ parameters = ASNIV}) when (Algo == ?'desCBC') or
+ (Algo == ?'des-EDE3-CBC') ->
%% This is an so called open ASN1-type that in this
%% case will be an octet-string of length 8
<<?ASN1_OCTET_STR_TAG, ?IV_LEN, IV:?IV_LEN/binary>> = ASNIV,
@@ -145,7 +148,8 @@ blocks(1, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
<<Acc/binary, XorSum/binary>>;
blocks(NumBlocks, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
XorSum = xor_sum(Password, Salt, Count, Index, Prf, PrfLen),
- blocks(NumBlocks -1, N, Index +1, Password, Salt, Count, Prf, PrfLen, <<Acc/binary, XorSum/binary>>).
+ blocks(NumBlocks -1, N, Index +1, Password, Salt, Count, Prf,
+ PrfLen, <<Acc/binary, XorSum/binary>>).
xor_sum(Password, Salt, Count, Index, Prf, PrfLen) ->
Result = Prf(Password, [Salt,<<Index:32/unsigned-big-integer>>], PrfLen),
@@ -172,11 +176,13 @@ key_derivation_params(#'PBES2-params'{keyDerivationFunc = KeyDerivationFunc,
#'PBES2-params_encryptionScheme'{algorithm = Algo} = EncScheme,
{PseudoRandomFunction, PseudoOtputLen} = pseudo_random_function(Prf),
KeyLen = derived_key_length(Algo, Length),
- {iolist_to_binary(OctetSalt), Count, KeyLen, PseudoRandomFunction, PseudoOtputLen, iv(EncScheme)}.
+ {OctetSalt, Count, KeyLen,
+ PseudoRandomFunction, PseudoOtputLen, iv(EncScheme)}.
-%% This function currently matches a tuple that ougth to be the value ?'id-hmacWithSHA1,
-%% but we need some kind of ASN1-fix for this.
-pseudo_random_function(#'PBKDF2-params_prf'{algorithm = {_,_, _,'id-hmacWithSHA1'}}) ->
+%% This function currently matches a tuple that ougth to be the value
+%% ?'id-hmacWithSHA1, but we need some kind of ASN1-fix for this.
+pseudo_random_function(#'PBKDF2-params_prf'{algorithm =
+ {_,_, _,'id-hmacWithSHA1'}}) ->
{fun crypto:sha_mac/3, pseudo_output_length(?'id-hmacWithSHA1')}.
pseudo_output_length(?'id-hmacWithSHA1') ->
@@ -184,11 +190,14 @@ pseudo_output_length(?'id-hmacWithSHA1') ->
derived_key_length(_, Len) when is_integer(Len) ->
Len;
-derived_key_length(Cipher,_) when (Cipher == ?'desCBC') or (Cipher == "DES-CBC") ->
+derived_key_length(Cipher,_) when (Cipher == ?'desCBC') or
+ (Cipher == "DES-CBC") ->
8;
-derived_key_length(Cipher,_) when (Cipher == ?'rc2CBC') or (Cipher == "RC2-CBC") ->
+derived_key_length(Cipher,_) when (Cipher == ?'rc2CBC') or
+ (Cipher == "RC2-CBC") ->
16;
-derived_key_length(Cipher,_) when (Cipher == ?'des-EDE3-CBC') or (Cipher == "DES-EDE3-CBC") ->
+derived_key_length(Cipher,_) when (Cipher == ?'des-EDE3-CBC') or
+ (Cipher == "DES-EDE3-CBC") ->
24.
cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'desCBC'}) ->
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index f19aab0533..910473d629 100644
--- a/lib/public_key/src/pubkey_pem.erl
+++ b/lib/public_key/src/pubkey_pem.erl
@@ -43,8 +43,6 @@
-include("public_key.hrl").
-export([encode/1, decode/1, decipher/2, cipher/3]).
-%% Backwards compatibility
-%%-export([decode_key/2]).
-define(ENCODED_LINE_LENGTH, 64).
@@ -69,26 +67,22 @@ encode(PemEntries) ->
encode_pem_entries(PemEntries).
%%--------------------------------------------------------------------
--spec decipher({pki_asn1_type(), DerEncrypted::binary(), term()},
- %%{Cipher :: string(),
- %%Salt :: binary()}},
- string()) -> Der::binary().
+-spec decipher({pki_asn1_type(), DerEncrypted::binary(),
+ {Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}}},
+ string()) -> Der::binary().
%%
%% Description: Deciphers a decrypted pem entry.
%%--------------------------------------------------------------------
decipher({_, DecryptDer, {Cipher, KeyDevParams}}, Password) ->
- %%decode_key(DecryptDer, Password, Cipher, Salt).
pubkey_pbe:decode(DecryptDer, Password, Cipher, KeyDevParams).
%%--------------------------------------------------------------------
--spec cipher(Der::binary(), term(),
-%%{Cipher :: string(), Hash::atom(), Salt :: binary()} ,
+-spec cipher(Der::binary(), {Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}} ,
string()) -> binary().
%%
%% Description: Ciphers a PEM entry
%%--------------------------------------------------------------------
cipher(Der, {Cipher, KeyDevParams}, Password)->
- %%encode_key(Der, Password, Cipher, Salt).
pubkey_pbe:encode(Der, Password, Cipher, KeyDevParams).
%%--------------------------------------------------------------------
@@ -100,7 +94,7 @@ encode_pem_entries(Entries) ->
encode_pem_entry({Type, Der, not_encrypted}) ->
StartStr = pem_start(Type),
[StartStr, "\n", b64encode_and_split(Der), "\n", pem_end(StartStr) ,"\n\n"];
-encode_pem_entry({Type, Der, {Cipher, {_, Salt}}}) ->
+encode_pem_entry({Type, Der, {Cipher, Salt}}) ->
StartStr = pem_start(Type),
[StartStr,"\n", pem_decrypt(),"\n", pem_decrypt_info(Cipher, Salt),"\n",
b64encode_and_split(Der), "\n", pem_end(StartStr) ,"\n\n"].
@@ -126,7 +120,7 @@ decode_pem_entry(Start, [<<"Proc-Type: 4,ENCRYPTED", _/binary>>, Line | Lines])
Decoded = base64:mime_decode(Cs),
[_, DekInfo0] = string:tokens(binary_to_list(Line), ": "),
[Cipher, Salt] = string:tokens(DekInfo0, ","),
- {Type, Decoded, {Cipher, {salt, unhex(Salt)}}};
+ {Type, Decoded, {Cipher, unhex(Salt)}};
decode_pem_entry(Start, Lines) ->
Type = asn1_type(Start),
Cs = erlang:iolist_to_binary(Lines),
@@ -140,9 +134,9 @@ decode_pem_entry(Start, Lines) ->
decode_encrypted_private_keyinfo(Der) ->
#'EncryptedPrivateKeyInfo'{encryptionAlgorithm = AlgorithmInfo,
- encryptedData = Data} = public_key:der_decode('EncryptedPrivateKeyInfo', Der),
- DecryptParams = pubkey_pbe:decrypt_parameters(AlgorithmInfo),
-
+ encryptedData = Data} =
+ public_key:der_decode('EncryptedPrivateKeyInfo', Der),
+ DecryptParams = pubkey_pbe:decrypt_parameters(AlgorithmInfo),
{'PrivateKeyInfo', iolist_to_binary(Data), DecryptParams}.
split_bin(Bin) ->
@@ -176,37 +170,6 @@ join_entry([<<"-----END ", _/binary>>| Lines], Entry) ->
join_entry([Line | Lines], Entry) ->
join_entry(Lines, [Line | Entry]).
-%% decode_key(Data, Password, "DES-CBC", Salt) ->
-%% Key = password_to_key(Password, Salt, 8),
-%% IV = Salt,
-%% crypto:des_cbc_decrypt(Key, IV, Data);
-%% decode_key(Data, Password, "DES-EDE3-CBC", Salt) ->
-%% Key = password_to_key(Password, Salt, 24),
-%% IV = Salt,
-%% <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
-%% crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data).
-
-%% encode_key(Data, Password, "DES-CBC", Salt) ->
-%% Key = password_to_key(Password, Salt, 8),
-%% IV = Salt,
-%% crypto:des_cbc_encrypt(Key, IV, Data);
-%% encode_key(Data, Password, "DES-EDE3-CBC", Salt) ->
-%% Key = password_to_key(Password, Salt, 24),
-%% IV = Salt,
-%% <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
-%% crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data).
-
-%% password_to_key(Data, Salt, KeyLen) ->
-%% <<Key:KeyLen/binary, _/binary>> =
-%% password_to_key(<<>>, Data, Salt, KeyLen, <<>>),
-%% Key.
-
-%% password_to_key(_, _, _, Len, Acc) when Len =< 0 ->
-%% Acc;
-%% password_to_key(Prev, Data, Salt, Len, Acc) ->
-%% M = crypto:md5([Prev, Data, Salt]),
-%% password_to_key(M, Data, Salt, Len - size(M), <<Acc/binary, M/binary>>).
-
unhex(S) ->
unhex(S, []).
@@ -273,11 +236,3 @@ pem_decrypt() ->
pem_decrypt_info(Cipher, Salt) ->
io_lib:format("DEK-Info: ~s,~s", [Cipher, lists:flatten(hexify(Salt))]).
-
-%%--------------------------------------------------------------------
-%%% Deprecated
-%%--------------------------------------------------------------------
-%% decode_key({_Type, Bin, not_encrypted}, _) ->
-%% Bin;
-%% decode_key({_Type, Bin, {Chipher,Salt}}, Password) ->
-%% decode_key(Bin, Password, Chipher, Salt).
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 19465e7828..753322b46d 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -45,13 +45,6 @@
ssh_decode/2, ssh_encode/2
]).
-%% Deprecated
-%% -export([decode_private_key/1, decode_private_key/2, pem_to_der/1]).
-
-%% -deprecated({pem_to_der, 1, next_major_release}).
-%% -deprecated({decode_private_key, 1, next_major_release}).
-%% -deprecated({decode_private_key, 2, next_major_release}).
-
-type rsa_padding() :: 'rsa_pkcs1_padding' | 'rsa_pkcs1_oaep_padding'
| 'rsa_no_padding'.
-type public_crypt_options() :: [{rsa_pad, rsa_padding()}].
@@ -104,20 +97,23 @@ pem_entry_decode({Asn1Type, Der, not_encrypted}) when is_atom(Asn1Type),
pem_entry_decode({Asn1Type, Der, not_encrypted}, _) when is_atom(Asn1Type),
is_binary(Der) ->
der_decode(Asn1Type, Der);
-pem_entry_decode({Asn1Type, CryptDer, {Cipher, _Params}} = PemEntry,
- Password) when is_atom(Asn1Type),
- is_binary(CryptDer),
+pem_entry_decode({Asn1Type, CryptDer, {Cipher, #'PBES2-params'{}}} = PemEntry,
+ Password) when is_atom(Asn1Type) andalso
+ is_binary(CryptDer) andalso
is_list(Cipher) ->
- Der = pubkey_pem:decipher(PemEntry, Password),
- der_decode(Asn1Type, Der).
+ do_pem_entry_decode(PemEntry, Password);
+pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
+ Password) when is_atom(Asn1Type) andalso
+ is_binary(CryptDer) andalso
+ is_list(Cipher) andalso
+ is_binary(Salt) andalso
+ erlang:byte_size(Salt) == 8 ->
+ do_pem_entry_decode(PemEntry, Password).
%%--------------------------------------------------------------------
-spec pem_entry_encode(pki_asn1_type(), term()) -> pem_entry().
--spec pem_entry_encode(pki_asn1_type(), term(),
- %%{{Cipher :: string(), Salt :: binary()}, string()}
- term()) ->
- pem_entry().
- %
+-spec pem_entry_encode(pki_asn1_type(), term(), term()) -> pem_entry().
+%%
%% Description: Creates a pem entry that can be feed to pem_encode/1.
%%--------------------------------------------------------------------
pem_entry_encode('SubjectPublicKeyInfo', Entity=#'RSAPublicKey'{}) ->
@@ -135,22 +131,27 @@ pem_entry_encode('SubjectPublicKeyInfo',
pem_entry_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
Der = der_encode(Asn1Type, Entity),
{Asn1Type, Der, not_encrypted}.
-pem_entry_encode(Asn1Type, Entity, {CipherInfo, Password}) when is_atom(Asn1Type),
- %%is_list(Cipher),
- %%is_binary(Salt),
- %%is_atom(Hash),
- %% erlang:byte_size(Salt) == 8,
- is_list(Password)->
- Der = der_encode(Asn1Type, Entity),
- DecryptDer = pubkey_pem:cipher(Der, CipherInfo, Password),
- {Asn1Type, DecryptDer, CipherInfo}.
-
+pem_entry_encode(Asn1Type, Entity, {{Cipher, #'PBES2-params'{}} = CipherInfo,
+ Password}) when is_atom(Asn1Type) andalso
+ is_list(Password) andalso
+ is_list(Cipher) ->
+ do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password);
+
+pem_entry_encode(Asn1Type, Entity, {{Cipher, Salt} = CipherInfo,
+ Password}) when is_atom(Asn1Type) andalso
+ is_list(Password) andalso
+ is_list(Cipher) andalso
+ is_binary(Salt) andalso
+ erlang:byte_size(Salt) == 8 ->
+ do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password).
+
%%--------------------------------------------------------------------
-spec der_decode(asn1_type(), Der::binary()) -> term().
%%
%% Description: Decodes a public key asn1 der encoded entity.
%%--------------------------------------------------------------------
-der_decode(Asn1Type, Der) when (Asn1Type == 'PrivateKeyInfo') or (Asn1Type == 'EncryptedPrivateKeyInfo')
+der_decode(Asn1Type, Der) when (Asn1Type == 'PrivateKeyInfo') or
+ (Asn1Type == 'EncryptedPrivateKeyInfo')
andalso is_binary(Der) ->
try
{ok, Decoded} = 'PKCS-FRAME':decode(Asn1Type, Der),
@@ -174,7 +175,8 @@ der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
%%
%% Description: Encodes a public key entity with asn1 DER encoding.
%%--------------------------------------------------------------------
-der_encode(Asn1Type, Entity) when Asn1Type == 'PrivateKeyInfo'; Asn1Type == 'EncryptedPrivateKeyInfo' ->
+der_encode(Asn1Type, Entity) when (Asn1Type == 'PrivateKeyInfo') or
+ (Asn1Type == 'EncryptedPrivateKeyInfo') ->
try
{ok, Encoded} = 'PKCS-FRAME':encode(Asn1Type, Entity),
iolist_to_binary(Encoded)
@@ -552,6 +554,14 @@ ssh_encode(Entries, Type) when is_list(Entries),
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
+do_pem_entry_encode(Asn1Type, Entity, CipherInfo, Password) ->
+ Der = der_encode(Asn1Type, Entity),
+ DecryptDer = pubkey_pem:cipher(Der, CipherInfo, Password),
+ {Asn1Type, DecryptDer, CipherInfo}.
+
+do_pem_entry_decode({Asn1Type,_, _} = PemEntry, Password) ->
+ Der = pubkey_pem:decipher(PemEntry, Password),
+ der_decode(Asn1Type, Der).
encrypt_public(PlainText, N, E, Options)->
Padding = proplists:get_value(rsa_pad, Options, rsa_pkcs1_padding),
@@ -649,20 +659,3 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
sized_binary(Binary) ->
Size = size(Binary),
<<?UINT32(Size), Binary/binary>>.
-
-%%--------------------------------------------------------------------
-%%% Deprecated functions
-%%--------------------------------------------------------------------
-%% pem_to_der(CertSource) ->
-%% {ok, Bin} = file:read_file(CertSource),
-%% {ok, pubkey_pem:decode(Bin)}.
-
-%% decode_private_key(KeyInfo) ->
-%% decode_private_key(KeyInfo, no_passwd).
-
-%% decode_private_key(KeyInfo = {'RSAPrivateKey', _, _}, Password) ->
-%% DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
-%% 'OTP-PUB-KEY':decode('RSAPrivateKey', DerEncoded);
-%% decode_private_key(KeyInfo = {'DSAPrivateKey', _, _}, Password) ->
-%% DerEncoded = pubkey_pem:decode_key(KeyInfo, Password),
-%% 'OTP-PUB-KEY':decode('DSAPrivateKey', DerEncoded).