Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions lib/dsa.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 12 additions & 8 deletions lib/ecc/ecdsa.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 17 additions & 12 deletions lib/elgamal.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 11 additions & 6 deletions src/dsa.iced
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,17 @@ class Pub extends BaseKey

verify : ([r, s], h, cb) ->
err = null
hi = @trunc_hash(h)
w = s.modInverse @q
u1 = hi.multiply(w).mod(@q)
u2 = r.multiply(w).mod(@q)
v = @g.modPow(u1, @p).multiply(@y.modPow(u2, @p)).mod(@p).mod(@q)
err = new Error "verification failed" unless v.equals(r)
if ((r.signum() <= 0) or (r.compareTo(@q) >= 0))
err = new Error "bad r"
else if ((s.signum() <= 0) or (s.compareTo(@q) >= 0))
err = new Error "bad s"
else
hi = @trunc_hash(h)
w = s.modInverse @q
u1 = hi.multiply(w).mod(@q)
u2 = r.multiply(w).mod(@q)
v = @g.modPow(u1, @p).multiply(@y.modPow(u2, @p)).mod(@p).mod(@q)
err = new Error "verification failed" unless v.equals(r)
cb err

#=================================================================
Expand Down
13 changes: 7 additions & 6 deletions src/ecc/ecdsa.iced
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,21 @@ class Pub extends BaseEccKey
err = null
hi = @trunc_hash(h)

if ((r.signum() <= 0) or (r.compareTo(@curve.p) > 0))
if ((r.signum() <= 0) or (r.compareTo(@curve.n) >= 0))
err = new Error "bad r"
else if ((r.signum() <= 0) or (s.compareTo(@curve.p) > 0))
else if ((s.signum() <= 0) or (s.compareTo(@curve.n) >= 0))
err = new Error "bad s"
else

n = @curve.n
w = s.modInverse n
u1 = hi.multiply(w).mod(n)
u2 = r.multiply(w).mod(n)
p = @curve.G.multiplyTwo(u1,@R,u2)

v = p.affineX.mod(n)
err = new Error "verification failed" unless v.equals(r)
if @curve.isInfinity(p)
err = new Error "verification failed"
else
v = p.affineX.mod(n)
err = new Error "verification failed" unless v.equals(r)
cb err

#=================================================================
Expand Down
9 changes: 7 additions & 2 deletions src/elgamal.iced
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,14 @@ class Priv extends BaseKey
#----------------

decrypt : (c, cb) ->
err = null
p = @pub.p
ret = c[0].modPow(@x,p).modInverse(p).multiply(c[1]).mod(p)
cb null, ret
if ((c[0].signum() <= 0) or (c[0].compareTo(p) >= 0)) or
((c[1].signum() <= 0) or (c[1].compareTo(p) >= 0))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AMarcedone does this look good? encrypt returns both values mod p so in principle honest ciphertext should be in that range

err = new Error "invalid message"
else
ret = c[0].modPow(@x,p).modInverse(p).multiply(c[1]).mod(p)
cb err, ret

#=================================================================

Expand Down
1 change: 1 addition & 0 deletions test/browser/main.iced
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

mods =
bn : require '../files/bn.iced'
brainpool256 : require '../files/brainpool256.iced'
brainpool384: require '../files/brainpool384.iced'
brainpool512: require '../files/brainpool512.iced'
Expand Down
41 changes: 41 additions & 0 deletions test/files/bn.iced
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{nbs,BigInteger} = require '../../lib/bn'

#=================================================================

exports.valid_mod_inverse_returns_inverse = (T, cb) ->
cases = [
{ a : '3', m : '257', inverse : '86' }
{ a : '10', m : '17', inverse : '12' }
{ a : '101', m : '257', inverse : '28' }
]

for c in cases
a = nbs c.a
m = nbs c.m
inv = a.modInverse m
T.equal inv.toString(), c.inverse, "#{c.a}^-1 mod #{c.m}"
T.equal a.multiply(inv).mod(m).toString(), '1', "#{c.a} * inverse == 1 mod #{c.m}"
cb()

#=================================================================

exports.invalid_mod_inverse_returns_zero_when_gcd_is_not_one = (T, cb) ->

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am kinda nervous at this function returning 0 when there is no inverse. Not saying we should change it in this PR, but if I were to write this again I would throw instead.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems to be the bignum library doing that, maybe we should swap it to another one going forward long term. Initially I was going to monkey-patch it but that's kind of ugly. This is just a test to understand and lock in curreent behavior.

cases = [
{ a : '2', m : '4' }
{ a : '6', m : '9' }
{ a : '101', m : '101' }
{ a : '202', m : '101' }
{ a : '3', m : '0' }
]

for c in cases
a = nbs c.a
m = nbs c.m
inv = a.modInverse m
T.equal inv.signum(), 0, "#{c.a}^-1 mod #{c.m} returned zero"
T.equal inv.toString(), '0'
unless m.signum() is 0
T.assert not(a.gcd(m).equals(BigInteger.ONE)), "#{c.a} and #{c.m} are not coprime"
cb()

#=================================================================
Loading