| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Copyright 2009 The Go Authors. All rights reserved. | 5 // Copyright 2009 The Go Authors. All rights reserved. |
| 6 // Use of this source code is governed by a BSD-style | 6 // Use of this source code is governed by a BSD-style |
| 7 // license that can be found in the LICENSE file. | 7 // license that can be found in the LICENSE file. |
| 8 | 8 |
| 9 /* | 9 /* |
| 10 * Copyright (c) 2003-2005 Tom Wu | 10 * Copyright (c) 2003-2005 Tom Wu |
| (...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 | 1111 y = (y*(2 - (x & 0xff)*y)) & 0xff; // y == 1/x mod 2^8 |
| 1112 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 | 1112 y = (y*(2 - (((x & 0xffff)*y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 |
| 1113 // Last step - calculate inverse mod DIGIT_BASE directly; | 1113 // Last step - calculate inverse mod DIGIT_BASE directly; |
| 1114 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. | 1114 // Assumes 16 < DIGIT_BITS <= 32 and assumes ability to handle 48-bit ints. |
| 1115 y = (y*(2 - x*y % DIGIT_BASE)) % DIGIT_BASE; // y == 1/x mod DIGIT_BASE | 1115 y = (y*(2 - x*y % DIGIT_BASE)) % DIGIT_BASE; // y == 1/x mod DIGIT_BASE |
| 1116 // We really want the negative inverse, and - DIGIT_BASE < y < DIGIT_BASE. | 1116 // We really want the negative inverse, and - DIGIT_BASE < y < DIGIT_BASE. |
| 1117 return (y > 0) ? DIGIT_BASE - y : -y; | 1117 return (y > 0) ? DIGIT_BASE - y : -y; |
| 1118 } | 1118 } |
| 1119 | 1119 |
| 1120 // TODO(regis): Make this method private once the plumbing to invoke it from | 1120 // TODO(regis): Make this method private once the plumbing to invoke it from |
| 1121 // dart:math is in place. | 1121 // dart:math is in place. Move the argument checking to dart:math. |
| 1122 // Return pow(this, e) % m. | 1122 // Return pow(this, e) % m. |
| 1123 int modPow(int e, int m) { | 1123 int modPow(int e, int m) { |
| 1124 // TODO(regis): Where/how do we handle values of e smaller than 256? | 1124 if (e is! int) throw new ArgumentError(e); |
| 1125 // TODO(regis): Where/how do we handle even values of m? | 1125 if (m is! int) throw new ArgumentError(m); |
| 1126 assert(e >= 256 && !m.isEven()); | 1126 int i = e.bitLength; |
| 1127 if (e is! _Bigint) { | 1127 if (i <= 0) return 1; |
| 1128 _Reduction z = new _Montgomery(m); | 1128 if ((e is! _Bigint) || m.isEven) { |
| 1129 _Reduction z = (i < 8 || m.isEven) ? new _Classic(m) : new _Montgomery(m); |
| 1130 // TODO(regis): Should we use Barrett reduction for an even modulus? |
| 1129 var r = new _Bigint(); | 1131 var r = new _Bigint(); |
| 1130 var r2 = new _Bigint(); | 1132 var r2 = new _Bigint(); |
| 1131 var g = z._convert(this); | 1133 var g = z._convert(this); |
| 1132 int i = _nbits(e) - 1; | 1134 i--; |
| 1133 g._copyTo(r); | 1135 g._copyTo(r); |
| 1134 while (--i >= 0) { | 1136 while (--i >= 0) { |
| 1135 z._sqrTo(r, r2); | 1137 z._sqrTo(r, r2); |
| 1136 if ((e & (1 << i)) > 0) { | 1138 if ((e & (1 << i)) != 0) { |
| 1137 z._mulTo(r2, g, r); | 1139 z._mulTo(r2, g, r); |
| 1138 } else { | 1140 } else { |
| 1139 var t = r; | 1141 var t = r; |
| 1140 r = r2; | 1142 r = r2; |
| 1141 r2 = t; | 1143 r2 = t; |
| 1142 } | 1144 } |
| 1143 } | 1145 } |
| 1144 return z._revert(r)._toValidInt(); | 1146 return z._revert(r)._toValidInt(); |
| 1145 } | 1147 } |
| 1146 var i = e.bitLength; | |
| 1147 var k; | 1148 var k; |
| 1148 var r = new _Bigint()._setInt(1); | |
| 1149 if (i <= 0) return r; | |
| 1150 // TODO(regis): Are these values of k really optimal for our implementation? | 1149 // TODO(regis): Are these values of k really optimal for our implementation? |
| 1151 else if (i < 18) k = 1; | 1150 if (i < 18) k = 1; |
| 1152 else if (i < 48) k = 3; | 1151 else if (i < 48) k = 3; |
| 1153 else if (i < 144) k = 4; | 1152 else if (i < 144) k = 4; |
| 1154 else if (i < 768) k = 5; | 1153 else if (i < 768) k = 5; |
| 1155 else k = 6; | 1154 else k = 6; |
| 1156 _Reduction z = new _Montgomery(m); | 1155 _Reduction z = new _Montgomery(m); |
| 1157 var n = 3; | 1156 var n = 3; |
| 1158 var k1 = k - 1; | 1157 var k1 = k - 1; |
| 1159 var km = (1 << k) - 1; | 1158 var km = (1 << k) - 1; |
| 1160 List g = new List(km + 1); | 1159 List g = new List(km + 1); |
| 1161 g[1] = z._convert(this); | 1160 g[1] = z._convert(this); |
| 1162 if (k > 1) { | 1161 if (k > 1) { |
| 1163 var g2 = new _Bigint(); | 1162 var g2 = new _Bigint(); |
| 1164 z._sqrTo(g[1], g2); | 1163 z._sqrTo(g[1], g2); |
| 1165 while (n <= km) { | 1164 while (n <= km) { |
| 1166 g[n] = new _Bigint(); | 1165 g[n] = new _Bigint(); |
| 1167 z._mulTo(g2, g[n - 2], g[n]); | 1166 z._mulTo(g2, g[n - 2], g[n]); |
| 1168 n += 2; | 1167 n += 2; |
| 1169 } | 1168 } |
| 1170 } | 1169 } |
| 1171 var j = e._used - 1; | 1170 var j = e._used - 1; |
| 1172 var w; | 1171 var w; |
| 1173 var is1 = true; | 1172 var is1 = true; |
| 1173 var r = new _Bigint()._setInt(1); |
| 1174 var r2 = new _Bigint(); | 1174 var r2 = new _Bigint(); |
| 1175 var t; | 1175 var t; |
| 1176 i = _nbits(e._digits[j]) - 1; | 1176 i = _nbits(e._digits[j]) - 1; |
| 1177 while (j >= 0) { | 1177 while (j >= 0) { |
| 1178 if (i >= k1) { | 1178 if (i >= k1) { |
| 1179 w = (e._digits[j] >> (i - k1)) & km; | 1179 w = (e._digits[j] >> (i - k1)) & km; |
| 1180 } else { | 1180 } else { |
| 1181 w = (e._digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); | 1181 w = (e._digits[j] & ((1 << (i + 1)) - 1)) << (k1 - i); |
| 1182 if (j > 0) { | 1182 if (j > 0) { |
| 1183 w |= e._digits[j - 1] >> (DIGIT_BITS + i - k1); | 1183 w |= e._digits[j - 1] >> (DIGIT_BITS + i - k1); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1220 if (--i < 0) { | 1220 if (--i < 0) { |
| 1221 i = DIGIT_BITS - 1; | 1221 i = DIGIT_BITS - 1; |
| 1222 --j; | 1222 --j; |
| 1223 } | 1223 } |
| 1224 } | 1224 } |
| 1225 } | 1225 } |
| 1226 return z._revert(r)._toValidInt(); | 1226 return z._revert(r)._toValidInt(); |
| 1227 } | 1227 } |
| 1228 } | 1228 } |
| 1229 | 1229 |
| 1230 // New classes to support crypto (modPow method). | 1230 // Interface for modular reduction. |
| 1231 | |
| 1232 class _Reduction { | 1231 class _Reduction { |
| 1233 const _Reduction(); | 1232 _Bigint _convert(_Bigint x); |
| 1234 _Bigint _convert(_Bigint x) => x; | 1233 _Bigint _revert(_Bigint x); |
| 1235 _Bigint _revert(_Bigint x) => x; | 1234 void _mulTo(_Bigint x, _Bigint y, _Bigint r); |
| 1236 | 1235 void _sqrTo(_Bigint x, _Bigint r); |
| 1237 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | |
| 1238 x._mulTo(y, r); | |
| 1239 } | |
| 1240 | |
| 1241 void _sqrTo(_Bigint x, _Bigint r) { | |
| 1242 x._sqrTo(r); | |
| 1243 } | |
| 1244 } | 1236 } |
| 1245 | 1237 |
| 1246 // Montgomery reduction on _Bigint. | 1238 // Montgomery reduction on _Bigint. |
| 1247 class _Montgomery implements _Reduction { | 1239 class _Montgomery implements _Reduction { |
| 1248 final _Bigint _m; | 1240 _Bigint _m; |
| 1249 var _mp; | 1241 var _mp; |
| 1250 var _mpl; | 1242 var _mpl; |
| 1251 var _mph; | 1243 var _mph; |
| 1252 var _um; | 1244 var _um; |
| 1253 var _mused2; | 1245 var _mused2; |
| 1254 | 1246 |
| 1255 _Montgomery(this._m) { | 1247 _Montgomery(m) { |
| 1248 _m = m._toBigint(); |
| 1256 _mp = _m._invDigit(); | 1249 _mp = _m._invDigit(); |
| 1257 _mpl = _mp & _Bigint.DIGIT2_MASK; | 1250 _mpl = _mp & _Bigint.DIGIT2_MASK; |
| 1258 _mph = _mp >> _Bigint.DIGIT2_BITS; | 1251 _mph = _mp >> _Bigint.DIGIT2_BITS; |
| 1259 _um = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; | 1252 _um = (1 << (_Bigint.DIGIT_BITS - _Bigint.DIGIT2_BITS)) - 1; |
| 1260 _mused2 = 2*_m._used; | 1253 _mused2 = 2*_m._used; |
| 1261 } | 1254 } |
| 1262 | 1255 |
| 1263 // Return x*R mod _m | 1256 // Return x*R mod _m |
| 1264 _Bigint _convert(_Bigint x) { | 1257 _Bigint _convert(_Bigint x) { |
| 1265 var r = new _Bigint(); | 1258 var r = new _Bigint(); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 _reduce(r); | 1309 _reduce(r); |
| 1317 } | 1310 } |
| 1318 | 1311 |
| 1319 // r = x*y/R mod _m ; x, y != r | 1312 // r = x*y/R mod _m ; x, y != r |
| 1320 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { | 1313 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { |
| 1321 x._mulTo(y, r); | 1314 x._mulTo(y, r); |
| 1322 _reduce(r); | 1315 _reduce(r); |
| 1323 } | 1316 } |
| 1324 } | 1317 } |
| 1325 | 1318 |
| 1319 // Modular reduction using "classic" algorithm. |
| 1320 class _Classic implements _Reduction { |
| 1321 _Bigint _m; |
| 1322 |
| 1323 _Classic(int m) { |
| 1324 _m = m._toBigint(); |
| 1325 } |
| 1326 |
| 1327 _Bigint _convert(_Bigint x) { |
| 1328 if (x._neg || x._compareTo(_m) >= 0) { |
| 1329 var r = new _Bigint(); |
| 1330 x._divRemTo(_m, null, r); |
| 1331 if (x._neg && !r._neg && r._used > 0) { |
| 1332 _m._subTo(r, r); |
| 1333 } |
| 1334 return r; |
| 1335 } |
| 1336 return x; |
| 1337 } |
| 1338 |
| 1339 _Bigint _revert(_Bigint x) { |
| 1340 return x; |
| 1341 } |
| 1342 |
| 1343 void _reduce(_Bigint x) { |
| 1344 x._divRemTo(_m, null, x); |
| 1345 } |
| 1346 |
| 1347 void _sqrTo(_Bigint x, _Bigint r) { |
| 1348 x._sqrTo(r); |
| 1349 _reduce(r); |
| 1350 } |
| 1351 |
| 1352 void _mulTo(_Bigint x, _Bigint y, _Bigint r) { |
| 1353 x._mulTo(y, r); |
| 1354 _reduce(r); |
| 1355 } |
| 1356 } |
| OLD | NEW |