aboutsummaryrefslogtreecommitdiffstats
path: root/lib/public_key/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/public_key/src')
-rw-r--r--lib/public_key/src/Makefile6
-rw-r--r--lib/public_key/src/pubkey_pbe.erl213
-rw-r--r--lib/public_key/src/pubkey_pem.erl81
-rw-r--r--lib/public_key/src/public_key.app.src4
-rw-r--r--lib/public_key/src/public_key.appup.src74
-rw-r--r--lib/public_key/src/public_key.erl102
6 files changed, 315 insertions, 165 deletions
diff --git a/lib/public_key/src/Makefile b/lib/public_key/src/Makefile
index 5a24b02d2a..062c495a65 100644
--- a/lib/public_key/src/Makefile
+++ b/lib/public_key/src/Makefile
@@ -42,10 +42,11 @@ MODULES = \
public_key \
pubkey_pem \
pubkey_ssh \
+ pubkey_pbe \
pubkey_cert \
- pubkey_cert_records
+ pubkey_cert_records
-HRL_FILES = $(INCLUDE)/public_key.hrl
+HRL_FILES = $(INCLUDE)/public_key.hrl
INTERNAL_HRL_FILES =
@@ -109,4 +110,3 @@ release_spec: opt
$(INSTALL_DATA) $(TARGET_FILES) $(APP_TARGET) $(APPUP_TARGET) $(RELSYSDIR)/ebin
release_docs_spec:
-
diff --git a/lib/public_key/src/pubkey_pbe.erl b/lib/public_key/src/pubkey_pbe.erl
new file mode 100644
index 0000000000..43f6c42f10
--- /dev/null
+++ b/lib/public_key/src/pubkey_pbe.erl
@@ -0,0 +1,213 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2011-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+%% Description: Implements Password Based Encryption PKCS-5, RFC-2898
+
+-module(pubkey_pbe).
+
+-include("public_key.hrl").
+
+-export([encode/4, decode/4, decrypt_parameters/1]).
+-export([pbdkdf1/4, pbdkdf2/6]).
+
+-define(DEFAULT_SHA_MAC_KEYLEN, 20).
+-define(ASN1_OCTET_STR_TAG, 4).
+-define(IV_LEN, 8).
+
+%%====================================================================
+%% Internal application API
+%%====================================================================
+
+%%--------------------------------------------------------------------
+-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);
+
+encode(Data, Password, "DES-EDE3-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
+ crypto:des_ede3_cbc_encrypt(Key1, Key2, Key3, IV, Data);
+
+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);
+
+decode(Data, Password,"DES-EDE3-CBC" = Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ <<Key1:8/binary, Key2:8/binary, Key3:8/binary>> = Key,
+ crypto:des_ede3_cbc_decrypt(Key1, Key2, Key3, IV, Data);
+
+decode(Data, Password,"RC2-CBC"= Cipher, KeyDevParams) ->
+ {Key, IV} = password_to_key_and_iv(Password, Cipher, KeyDevParams),
+ crypto:rc2_cbc_decrypt(Key, IV, Data).
+
+%%--------------------------------------------------------------------
+-spec pbdkdf1(string(), iodata(), integer(), atom()) -> binary().
+%%
+%% Description: Implements password based decryption key derive function 1.
+%% Exported mainly for testing purposes.
+%%--------------------------------------------------------------------
+pbdkdf1(_, _, 0, Acc) ->
+ Acc;
+pbdkdf1(Password, Salt, Count, Hash) ->
+ Result = crypto:Hash([Password, Salt]),
+ do_pbdkdf1(Result, Count-1, Result, Hash).
+
+%%--------------------------------------------------------------------
+-spec pbdkdf2(string(), iodata(), integer(), integer(), fun(), integer())
+ -> binary().
+%%
+%% Description: Implements password based decryption key derive function 2.
+%% Exported mainly for testing purposes.
+%%--------------------------------------------------------------------
+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 decrypt_parameters(#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{}) ->
+ {Cipher::string(), #'PBES2-params'{}}.
+%%
+%% Description: Performs ANS1-decoding of encryption parameters.
+%%--------------------------------------------------------------------
+decrypt_parameters(#'EncryptedPrivateKeyInfo_encryptionAlgorithm'{
+ algorithm = Oid, parameters = Param}) ->
+ decrypt_parameters(Oid, Param).
+
+%%--------------------------------------------------------------------
+%%% Internal functions
+%%--------------------------------------------------------------------
+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),
+ %% Old PEM encryption does not use standard encryption method
+ %% pbdkdf1 and uses then salt as IV
+ {Key, Salt}.
+
+pem_encrypt(_, _, _, 0, Acc, _) ->
+ Acc;
+pem_encrypt(Prev, Password, Salt, Count, Acc, Hash) ->
+ Result = crypto:Hash([Prev, Password, Salt]),
+ pem_encrypt(Result, Password, Salt, Count-1 , <<Acc/binary, Result/binary>>, Hash).
+
+do_pbdkdf1(_, 0, Acc, _) ->
+ Acc;
+do_pbdkdf1(Prev, Count, Acc, Hash) ->
+ Result = crypto:Hash(Prev),
+ 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') ->
+ %% 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,
+ IV;
+iv(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC',
+ parameters = ASN1IV}) ->
+ {ok, #'RC2-CBC-Parameter'{iv = IV}} = 'PKCS-FRAME':decode('RC2-CBC-Parameter', ASN1IV),
+ iolist_to_binary(IV).
+
+blocks(1, N, Index, Password, Salt, Count, Prf, PrfLen, Acc) ->
+ <<XorSum:N/binary, _/binary>> = xor_sum(Password, Salt, Count, Index, Prf, PrfLen),
+ <<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>>).
+
+xor_sum(Password, Salt, Count, Index, Prf, PrfLen) ->
+ Result = Prf(Password, [Salt,<<Index:32/unsigned-big-integer>>], PrfLen),
+ do_xor_sum(Prf, PrfLen, Result, Password, Count-1, Result).
+
+do_xor_sum(_, _, _, _, 0, Acc) ->
+ Acc;
+do_xor_sum(Prf, PrfLen, Prev, Password, Count, Acc)->
+ Result = Prf(Password, Prev, PrfLen),
+ do_xor_sum(Prf, PrfLen, Result, Password, Count-1, crypto:exor(Acc, Result)).
+
+decrypt_parameters(?'id-PBES2', DekParams) ->
+ {ok, Params} = 'PKCS-FRAME':decode('PBES2-params', DekParams),
+ {cipher(Params#'PBES2-params'.encryptionScheme), Params}.
+
+key_derivation_params(#'PBES2-params'{keyDerivationFunc = KeyDerivationFunc,
+ encryptionScheme = EncScheme}) ->
+ #'PBES2-params_keyDerivationFunc'{algorithm = ?'id-PBKDF2',
+ parameters =
+ #'PBKDF2-params'{salt = {specified, OctetSalt},
+ iterationCount = Count,
+ keyLength = Length,
+ prf = Prf}} = KeyDerivationFunc,
+ #'PBES2-params_encryptionScheme'{algorithm = Algo} = EncScheme,
+ {PseudoRandomFunction, PseudoOtputLen} = pseudo_random_function(Prf),
+ KeyLen = derived_key_length(Algo, Length),
+ {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'}}) ->
+ {fun crypto:sha_mac/3, pseudo_output_length(?'id-hmacWithSHA1')};
+pseudo_random_function(#'PBKDF2-params_prf'{algorithm = ?'id-hmacWithSHA1'}) ->
+ {fun crypto:sha_mac/3, pseudo_output_length(?'id-hmacWithSHA1')}.
+
+pseudo_output_length(?'id-hmacWithSHA1') ->
+ ?DEFAULT_SHA_MAC_KEYLEN.
+
+derived_key_length(_, Len) when is_integer(Len) ->
+ Len;
+derived_key_length(Cipher,_) when (Cipher == ?'desCBC') or
+ (Cipher == "DES-CBC") ->
+ 8;
+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") ->
+ 24.
+
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'desCBC'}) ->
+ "DES-CBC";
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'des-EDE3-CBC'}) ->
+ "DES-EDE3-CBC";
+cipher(#'PBES2-params_encryptionScheme'{algorithm = ?'rc2CBC'}) ->
+ "RC2-CBC".
+
+ceiling(Float) ->
+ erlang:round(Float + 0.5).
diff --git a/lib/public_key/src/pubkey_pem.erl b/lib/public_key/src/pubkey_pem.erl
index c26815bc04..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,23 +67,23 @@ encode(PemEntries) ->
encode_pem_entries(PemEntries).
%%--------------------------------------------------------------------
--spec decipher({pki_asn1_type(), DerEncrypted::binary(),{Cipher :: string(),
- Salt :: 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,Salt}}, Password) ->
- decode_key(DecryptDer, Password, Cipher, Salt).
+decipher({_, DecryptDer, {Cipher, KeyDevParams}}, Password) ->
+ pubkey_pbe:decode(DecryptDer, Password, Cipher, KeyDevParams).
%%--------------------------------------------------------------------
--spec cipher(Der::binary(),{Cipher :: string(), Salt :: binary()} ,
+-spec cipher(Der::binary(), {Cipher :: string(), Salt :: iodata() | #'PBES2-params'{}} ,
string()) -> binary().
%%
%% Description: Ciphers a PEM entry
%%--------------------------------------------------------------------
-cipher(Der, {Cipher,Salt}, Password)->
- encode_key(Der, Password, Cipher, Salt).
+cipher(Der, {Cipher, KeyDevParams}, Password)->
+ pubkey_pbe:encode(Der, Password, Cipher, KeyDevParams).
%%--------------------------------------------------------------------
%%% Internal functions
@@ -127,8 +125,20 @@ decode_pem_entry(Start, Lines) ->
Type = asn1_type(Start),
Cs = erlang:iolist_to_binary(Lines),
Decoded = base64:mime_decode(Cs),
- {Type, Decoded, not_encrypted}.
-
+ case Type of
+ 'EncryptedPrivateKeyInfo'->
+ decode_encrypted_private_keyinfo(Decoded);
+ _ ->
+ {Type, Decoded, not_encrypted}
+ end.
+
+decode_encrypted_private_keyinfo(Der) ->
+ #'EncryptedPrivateKeyInfo'{encryptionAlgorithm = AlgorithmInfo,
+ encryptedData = Data} =
+ public_key:der_decode('EncryptedPrivateKeyInfo', Der),
+ DecryptParams = pubkey_pbe:decrypt_parameters(AlgorithmInfo),
+ {'PrivateKeyInfo', iolist_to_binary(Data), DecryptParams}.
+
split_bin(Bin) ->
split_bin(0, Bin).
@@ -160,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, []).
@@ -228,6 +207,10 @@ pem_end(<<"-----BEGIN DSA PRIVATE KEY-----">>) ->
<<"-----END DSA PRIVATE KEY-----">>;
pem_end(<<"-----BEGIN DH PARAMETERS-----">>) ->
<<"-----END DH PARAMETERS-----">>;
+pem_end(<<"-----BEGIN PRIVATE KEY-----">>) ->
+ <<"-----END PRIVATE KEY-----">>;
+pem_end(<<"-----BEGIN ENCRYPTED PRIVATE KEY-----">>) ->
+ <<"-----END ENCRYPTED PRIVATE KEY-----">>;
pem_end(_) ->
undefined.
@@ -242,18 +225,14 @@ asn1_type(<<"-----BEGIN PUBLIC KEY-----">>) ->
asn1_type(<<"-----BEGIN DSA PRIVATE KEY-----">>) ->
'DSAPrivateKey';
asn1_type(<<"-----BEGIN DH PARAMETERS-----">>) ->
- 'DHParameter'.
+ 'DHParameter';
+asn1_type(<<"-----BEGIN PRIVATE KEY-----">>) ->
+ 'PrivateKeyInfo';
+asn1_type(<<"-----BEGIN ENCRYPTED PRIVATE KEY-----">>) ->
+ 'EncryptedPrivateKeyInfo'.
pem_decrypt() ->
<<"Proc-Type: 4,ENCRYPTED">>.
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.app.src b/lib/public_key/src/public_key.app.src
index 1963bd05d4..4cc81ea573 100644
--- a/lib/public_key/src/public_key.app.src
+++ b/lib/public_key/src/public_key.app.src
@@ -3,10 +3,12 @@
{vsn, "%VSN%"},
{modules, [ public_key,
pubkey_pem,
+ pubkey_pbe,
pubkey_ssh,
pubkey_cert,
pubkey_cert_records,
- 'OTP-PUB-KEY'
+ 'OTP-PUB-KEY',
+ 'PKCS-FRAME'
]},
{applications, [crypto, kernel, stdlib]},
{registered, []},
diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src
index 4986801dad..2945fb1213 100644
--- a/lib/public_key/src/public_key.appup.src
+++ b/lib/public_key/src/public_key.appup.src
@@ -1,70 +1,16 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"0.11",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {add_module, pubkey_ssh, soft, soft_purge, soft_purge},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
-
- {"0.10",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.9",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.8",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- }
+ {"0.13", [{restart_application, public_key}]},
+ {"0.11", [{restart_application, public_key}]},
+ {"0.10", [{restart_application, public_key}]},
+ {"0.9", [{restart_application, public_key}]},
+ {"0.8", [{restart_application, public_key}]}
],
[
- {"0.11",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {delete_module, pubkey_ssh, soft, soft_purge, soft_purge},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
-
- {"0.10",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.9",
- [
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.8",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- }
+ {"0.13", [{restart_application, public_key}]},
+ {"0.11", [{restart_application, public_key}]},
+ {"0.10", [{restart_application, public_key}]},
+ {"0.9", [{restart_application, public_key}]},
+ {"0.8", [{restart_application, public_key}]}
]}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 33fcce2c44..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,22 +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, #'PBES2-params'{}}} = PemEntry,
+ Password) when is_atom(Asn1Type) andalso
+ is_binary(CryptDer) andalso
+ is_list(Cipher) ->
+ do_pem_entry_decode(PemEntry, Password);
pem_entry_decode({Asn1Type, CryptDer, {Cipher, Salt}} = PemEntry,
- Password) when is_atom(Asn1Type),
- is_binary(CryptDer),
- is_list(Cipher),
- is_binary(Salt),
- erlang:byte_size(Salt) == 8
- ->
- Der = pubkey_pem:decipher(PemEntry, Password),
- der_decode(Asn1Type, Der).
+ 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()}) ->
- 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'{}) ->
@@ -137,21 +131,36 @@ 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,
- {{Cipher, Salt}= CipherInfo, Password}) when is_atom(Asn1Type),
- is_list(Cipher),
- is_binary(Salt),
- 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')
+ andalso is_binary(Der) ->
+ try
+ {ok, Decoded} = 'PKCS-FRAME':decode(Asn1Type, Der),
+ Decoded
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end;
+
der_decode(Asn1Type, Der) when is_atom(Asn1Type), is_binary(Der) ->
try
{ok, Decoded} = 'OTP-PUB-KEY':decode(Asn1Type, Der),
@@ -166,6 +175,16 @@ 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') or
+ (Asn1Type == 'EncryptedPrivateKeyInfo') ->
+ try
+ {ok, Encoded} = 'PKCS-FRAME':encode(Asn1Type, Entity),
+ iolist_to_binary(Encoded)
+ catch
+ error:{badmatch, {error, _}} = Error ->
+ erlang:error(Error)
+ end;
+
der_encode(Asn1Type, Entity) when is_atom(Asn1Type) ->
try
{ok, Encoded} = 'OTP-PUB-KEY':encode(Asn1Type, Entity),
@@ -535,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),
@@ -632,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).