~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to lib/ssh/src/ssh_rsa.erl

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%% ``The contents of this file are subject to the Erlang Public License,
 
2
%% Version 1.1, (the "License"); you may not use this file except in
 
3
%% compliance with the License. You should have received a copy of the
 
4
%% Erlang Public License along with this software. If not, it can be
 
5
%% retrieved via the world wide web at http://www.erlang.org/.
 
6
%% 
 
7
%% Software distributed under the License is distributed on an "AS IS"
 
8
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 
9
%% the License for the specific language governing rights and limitations
 
10
%% under the License.
 
11
%% 
 
12
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
 
13
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
 
14
%% AB. All Rights Reserved.''
 
15
%% 
 
16
%%     $Id$
 
17
%%
 
18
 
 
19
%%% Description: rsa public-key sign and verify
 
20
 
 
21
-module(ssh_rsa).
 
22
 
 
23
-export([verify/3, sign/2]).
 
24
-export([alg_name/0]).
 
25
 
 
26
-include("ssh.hrl").
 
27
-include("PKCS-1.hrl").
 
28
 
 
29
 
 
30
-define(MGF(Seed,Len), mgf1((Seed),(Len))).
 
31
-define(HASH(X), crypto:sha((X))).
 
32
-define(HLen, 20).
 
33
 
 
34
%% start() ->
 
35
%%     crypto:start().
 
36
 
 
37
%% sign_file(File) ->
 
38
%%     start(),
 
39
%%     {ok,Bin} = file:read_file(File),
 
40
%%     {ok,Key} = ssh_file:private_host_rsa_key(user),
 
41
%%     sign(Key, Bin).
 
42
 
 
43
%% verify_file(File, Sig) ->
 
44
%%     start(),
 
45
%%     {ok,Bin} = file:read_file(File),
 
46
%%     {ok,Key} = ssh_file:public_host_rsa_key(user),
 
47
%%     verify(Key, Bin, Sig).
 
48
 
 
49
sign(Private,Mb) ->
 
50
    rsassa_pkcs1_v1_5_sign(Private,Mb).
 
51
 
 
52
verify(Public,Mb,Sb) ->
 
53
    rsassa_pkcs1_v1_5_verify(Public,Mb,Sb).
 
54
 
 
55
 
 
56
 
 
57
%% Integer to octet string
 
58
i2osp(X, XLen) ->
 
59
    ssh_bits:i2bin(X, XLen).
 
60
 
 
61
%% Octet string to Integer
 
62
os2ip(X) ->
 
63
    ssh_bits:bin2i(X).
 
64
 
 
65
%% decrypt1, M = message representative
 
66
%% rsaep(#ssh_key { public={N,E}}, M) ->
 
67
%%     ?ssh_assert(M >= 0 andalso M =< N-1, out_of_range),
 
68
%%     ssh_math:ipow(M, E, N).
 
69
 
 
70
%% encrypt1, C = cipher representative
 
71
%% rsadp(#ssh_key { public={N,_}, private={_,D}}, C) ->
 
72
%%     ?ssh_assert(C >= 0 andalso C =< N-1, out_of_range),
 
73
%%     ssh_math:ipow(C, D, N).
 
74
 
 
75
%% sign1, M = message representative
 
76
rsasp1(#ssh_key { public={N,_}, private={_,D}}, M) ->
 
77
    ?ssh_assert((M >= 0 andalso M =< N-1), out_of_range),
 
78
    ssh_math:ipow(M, D, N).
 
79
 
 
80
%% verify1,  S =signature representative
 
81
rsavp1(#ssh_key { public={N,E}}, S)  ->
 
82
    ?ssh_assert(S >= 0 andalso S =< N-1, out_of_range),
 
83
    ssh_math:ipow(S, E, N).
 
84
 
 
85
 
 
86
%% M messaage
 
87
%% rsaes_oaep_encrypt(Public, M) ->
 
88
%%     rsaes_oaep_encrypt(Public, M, <<>>).
 
89
 
 
90
%% rsaes_oaep_encrypt(Public=#ssh_key { public={N,_E}}, M, L) ->
 
91
%%     ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
 
92
%%     K = (ssh_bits:isize(N)+7) div 8,
 
93
%%     MLen = size(M),
 
94
%%     %% LLen  = size(L),
 
95
%%     ?ssh_assert(MLen =< K - 2*?HLen - 2, message_to_long),
 
96
%%     LHash = ?HASH(L),
 
97
%%     PS = ssh_bits:fill_bits(K - MLen - 2*?HLen - 2, 0),
 
98
%%     DB = <<LHash/binary, PS/binary, 16#01, M/binary>>,
 
99
%%     Seed = ssh_bits:random(?HLen),
 
100
%%     DbMask = ?MGF(Seed, K - ?HLen - 1),
 
101
%%     MaskedDB = ssh_bits:xor_bits(DB, DbMask),
 
102
%%     SeedMask = ?MGF(MaskedDB, ?HLen),
 
103
%%     MaskedSeed = ssh_bits:xor_bits(Seed, SeedMask),
 
104
%%     EM = <<16#00, MaskedSeed/binary, MaskedDB/binary>>,
 
105
%%     Mc = os2ip(EM),
 
106
%%     C = rsaep(Public, Mc),
 
107
%%     i2osp(C, K).
 
108
 
 
109
%% rsaes_oaep_decrypt(Key, C) ->
 
110
%%     rsaes_oaep_decrypt(Key, C, <<>>).
 
111
 
 
112
%% rsaes_oaep_decrypt(Private=#ssh_key { public={N,_},private={_,_}},Cb,L) ->
 
113
%%     ?ssh_assert(size(L) =< 16#ffffffffffffffff, label_to_long),
 
114
%%     K = (ssh_bits:isize(N)+7) div 8,
 
115
%%     ?ssh_assert(K == 2*?HLen + 2, decryption_error),
 
116
%%     C = os2ip(Cb),
 
117
%%     M = rsadp(Private, C),
 
118
%%     EM = i2osp(M, K),
 
119
%%     LHash = ?HASH(L),
 
120
%%     MLen = K - ?HLen -1,
 
121
%%     case EM of
 
122
%%      <<16#00, MaskedSeed:?HLen/binary, MaskedDB:MLen>> ->
 
123
%%          SeedMask = ?MGF(MaskedDB, ?HLen),
 
124
%%          Seed = ssh_bits:xor_bits(MaskedSeed, SeedMask),
 
125
%%          DbMask = ?MGF(Seed, K - ?HLen - 1),
 
126
%%          DB = ssh_bits:xor_bits(MaskedDB, DbMask),
 
127
%%          PSLen = K - MLen - 2*?HLen - 2,
 
128
%%          case DB of
 
129
%%              <<LHash:?HLen, _PS:PSLen/binary, 16#01, M/binary>> ->
 
130
%%                  M;
 
131
%%              _ ->
 
132
%%                  exit(decryption_error)
 
133
%%          end;
 
134
%%      _ ->
 
135
%%          exit(decryption_error)
 
136
%%     end.
 
137
 
 
138
 
 
139
%% rsaes_pkcs1_v1_5_encrypt(Public=#ssh_key { public={N,_}}, M) ->    
 
140
%%     K = (ssh_bits:isize(N)+7) div 8,
 
141
%%     MLen = size(M),
 
142
%%     ?ssh_assert(MLen =< K - 11, message_to_long),
 
143
%%     PS = ssh_bits:random(K - MLen - 3),
 
144
%%     EM = <<16#00,16#02,PS/binary,16#00,M/binary>>,
 
145
%%     Mc = os2ip(EM),
 
146
%%     C = rsaep(Public, Mc),
 
147
%%     i2osp(C, K).
 
148
 
 
149
 
 
150
%% rsaes_pkcs1_v1_5_decrypt(Private=#ssh_key { public={N,_},private={_,_}},
 
151
%%                       Cb) ->
 
152
%%     K = (ssh_bits:isize(N)+7) div 8,
 
153
%%     CLen = size(Cb),
 
154
%%     ?ssh_assert(CLen == K andalso K >= 11, decryption_error),
 
155
%%     C = os2ip(Cb),
 
156
%%     M = rsadp(Private, C),
 
157
%%     EM = i2osp(M, K),
 
158
%%     PSLen = K - CLen - 3,
 
159
%%     case EM of
 
160
%%      <<16#00, 16#02, _PS:PSLen/binary, 16#00, M>> ->
 
161
%%          M;
 
162
%%      _ ->
 
163
%%          exit(decryption_error)
 
164
%%     end.
 
165
 
 
166
%% rsassa_pss_sign(Private=#ssh_key { public={N,_},private={_,_}},Mb) ->
 
167
%%     ModBits = ssh_bits:isize(N),
 
168
%%     K = (ModBits+7) div 8,
 
169
%%     EM = emsa_pss_encode(Mb, ModBits - 1),
 
170
%%     M = os2ip(EM),
 
171
%%     S = rsasp1(Private, M),
 
172
%%     i2osp(S, K).
 
173
 
 
174
%% rsassa_pss_verify(Public=#ssh_key { public={N,_E}},Mb,Sb) ->
 
175
%%     ModBits = ssh_bits:isize(N),
 
176
%%     K = (ModBits+7) div 8,
 
177
%%     ?ssh_assert(size(Sb) == K, invalid_signature),
 
178
%%     S = os2ip(Sb),
 
179
%%     M = rsavp1(Public,S),
 
180
%%     EMLen = (ModBits-1+7) div 8,
 
181
%%     EM = i2osp(M, EMLen),
 
182
%%     emsa_pss_verify(Mb, EM, ModBits-1).
 
183
 
 
184
 
 
185
rsassa_pkcs1_v1_5_sign(Private=#ssh_key { public={N,_},private={_,_D}},Mb) ->
 
186
    K = (ssh_bits:isize(N)+7) div 8,    
 
187
    EM = emsa_pkcs1_v1_5_encode(Mb, K),
 
188
    M = os2ip(EM),
 
189
    S = rsasp1(Private, M),
 
190
    i2osp(S, K).
 
191
 
 
192
rsassa_pkcs1_v1_5_verify(Public=#ssh_key { public={N,_E}}, Mb, Sb) ->
 
193
    K = (ssh_bits:isize(N)+7) div 8,
 
194
    ?ssh_assert(size(Sb) == K, invalid_signature),
 
195
    S = os2ip(Sb),
 
196
    M = rsavp1(Public, S),
 
197
    EM = i2osp(M, K),
 
198
    ?dbg(true, "verify K=~p S=~w\nM=~w\nEM=~w\n", [K, S, M, EM]),
 
199
    case emsa_pkcs1_v1_5_encode(Mb, K) of
 
200
        EM -> ok;
 
201
        _S -> {error, invalid_signature} % exit(invalid_signature)
 
202
    end.
 
203
 
 
204
 
 
205
emsa_pkcs1_v1_5_encode(M, EMLen) ->
 
206
    H = ?HASH(M),
 
207
    %% Must use speical xxNull types here!
 
208
    Alg = #'AlgorithmNull' { algorithm = ?'id-sha1',
 
209
                             parameters = <<>> },
 
210
    {ok,TCode} = asn1rt:encode('PKCS-1', 'DigestInfoNull',
 
211
                               #'DigestInfoNull' { digestAlgorithm = Alg,
 
212
                                                   digest = H }),
 
213
    T = list_to_binary(TCode),
 
214
    TLen = size(T),
 
215
    ?ssh_assert(EMLen >= TLen + 11, message_to_short),
 
216
    PS = ssh_bits:fill_bits(EMLen - TLen - 3, 16#ff),
 
217
    <<16#00, 16#01, PS/binary, 16#00, T/binary>>.
 
218
 
 
219
 
 
220
%% emsa_pss_encode(M, EMBits) ->
 
221
%%     emsa_pss_encode(M, EMBits, 0).
 
222
 
 
223
%% emsa_pss_encode(M, EMBits, SLen) ->
 
224
%%     ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
 
225
%%     EMLen = (EMBits + 7) div 8,
 
226
%%     MHash = ?HASH(M),
 
227
%%     ?ssh_assert(EMLen >= ?HLen + SLen + 2, encoding_error),
 
228
%%     Salt = ssh_bits:random(SLen),
 
229
%%     M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
 
230
%%        MHash, Salt],
 
231
%%     H = ?HASH(M1),
 
232
%%     PS = ssh_bits:fill_bits(EMLen-SLen-?HLen-2, 0),
 
233
%%     DB = <<PS/binary, 16#01, Salt/binary>>,
 
234
%%     DbMask = ?MGF(H, EMLen - ?HLen -1),
 
235
%%     MaskedDB = ssh_bits:xor_bits(DB, DbMask),
 
236
%%     ZLen = 8*EMLen - EMBits,
 
237
%%     NZLen = (8 - (ZLen rem 8)) rem 8,
 
238
%%     <<_:ZLen, NZ:NZLen, MaskedDB1/binary>> = MaskedDB,
 
239
%%     MaskedDB2 = <<0:ZLen, NZ:NZLen, MaskedDB1/binary>>,
 
240
%%     <<MaskedDB2/binary, H/binary, 16#BC>>.
 
241
 
 
242
 
 
243
%% emsa_pss_verify(M, EM, EMBits) ->
 
244
%%     emsa_pss_verify(M, EM, EMBits, 0).
 
245
 
 
246
%% emsa_pss_verify(M, EM, EMBits, SLen) ->
 
247
%%     ?ssh_assert(size(M) =< 16#ffffffffffffffff, message_to_long),
 
248
%%     EMLen = (EMBits + 7) div 8,
 
249
%%     MHash = ?HASH(M),
 
250
%%     ?ssh_assert(EMLen >= ?HLen + SLen + 2, inconsistent),
 
251
%%     MaskLen = (EMLen - ?HLen - 1)-1,
 
252
%%     ZLen = 8*EMLen - EMBits,
 
253
%%     NZLen = (8 - (ZLen rem 8)) rem 8,
 
254
%%     case EM of
 
255
%%      <<0:ZLen,Nz:NZLen,MaskedDB1:MaskLen/binary, H:?HLen/binary, 16#BC>> ->
 
256
%%          MaskedDB = <<0:ZLen,Nz:NZLen,MaskedDB1/binary>>,
 
257
%%          DbMask = ?MGF(H, EMLen - ?HLen - 1),
 
258
%%          DB = ssh_bits:xor_bits(MaskedDB, DbMask),
 
259
%%          PSLen1 = (EMLen - SLen - ?HLen - 2) - 1,
 
260
%%          PS = ssh_bits:fill_bits(PSLen1, 0),
 
261
%%          case DB of
 
262
%%              <<_:ZLen,0:NZLen,PS:PSLen1/binary,16#01,Salt:SLen/binary>> ->
 
263
%%                  M1 = [16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,
 
264
%%                        MHash, Salt],
 
265
%%                  case ?HASH(M1) of
 
266
%%                      H -> ok;
 
267
%%                      _ -> exit(inconsistent)
 
268
%%                  end;
 
269
%%              _ ->
 
270
%%                  exit(inconsistent)
 
271
%%          end;
 
272
%%      _ ->
 
273
%%          exit(inconsistent)
 
274
%%     end.
 
275
 
 
276
    
 
277
 
 
278
%% Mask generating function MGF1
 
279
%% mgf1(MGFSeed, MaskLen) ->
 
280
%%     T = mgf1_loop(0, ((MaskLen + ?HLen -1) div ?HLen) - 1, MGFSeed, ""),
 
281
%%     <<R:MaskLen/binary, _/binary>> = T,
 
282
%%     R.
 
283
 
 
284
%% mgf1_loop(Counter, N, _, T) when Counter > N ->
 
285
%%     list_to_binary(T);
 
286
%% mgf1_loop(Counter, N, MGFSeed, T) ->
 
287
%%     C = i2osp(Counter, 4),
 
288
%%     mgf1_loop(Counter+1, N, MGFSeed, [T, ?HASH([MGFSeed, C])]).
 
289
 
 
290
 
 
291
 
 
292
 
 
293
alg_name() ->
 
294
    "ssh-rsa".