1

Is there a function or method to find the inverse mod of say x and y in ruby?

Something like inverse(x,y) in the crypto library from python. I'm trying to use it to find d for a rsa implementation.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
Alloysius Goh
  • 141
  • 1
  • 1
  • 6
  • 3
    I think it would be helpful to give an example of X,Y and the expected output. – Viktor Sep 12 '18 at 07:49
  • @VIktor x = 65537; y = 147720936134669456975617202169086913591832713006137189368588334030836309672102601035425841462186510149328644813449230183610499071646822634720876665518383759084116646191872547556483674606856788893876905241722701088534271700867144889033866109547143838528365263186301950299926302293285507357594571617185598409976 – Alloysius Goh Sep 12 '18 at 13:25

3 Answers3

1

Brute force for small numbers:

def inv_mod(num, mod)
  res = nil
  (0..mod).each do |step|
    k = (step * mod) + 1
    return k / num if k % num == 0
   end
  res
end

inv_mod(7, 31) # => 9

There should be a faster algorithm over there.

iGian
  • 11,023
  • 3
  • 21
  • 36
0

Here is my implementation of algorithm from here.

def modInverse(a, m)
    (1..m).each{|x| break x if (a*x % m == 1)}
end
MOPO3OB
  • 383
  • 3
  • 16
-1

This code in ruby is calculating the inverse mod correctly:

https://gist.github.com/jingoro/2388745

# Some modular arithmetic helper methods useful for number theory or
# cryptography.
#
# # Examples
#
# Compute the greatest common denominator of 114 and 48:
#
#     gcd(114, 48) #=> 6
#
# Compute `a` and `b` such that `a*x + b*y = gcd(x, y)`:
#
#     g, a, b = gcdext(3, 5)
#     g #=> 1
#     a #=> 2
#     b #=> -1
#
# Compute the inverse of 4 modulo 7:
#
#     invert(4, 7) #=> 2
#
# Compute 3 raised to 4 modulo 5:
#
#     powmod(3, 4, 5) #=> 1
#
module ModularArithmetic

  module_function

  # Returns the greatest common denominator of `x` and `y`.
  #
  # @param [Integer] x
  # @param [Integer] y
  # @return [Integer]
  def gcd(x, y)
    gcdext(x, y).first
  end

  # Returns an array of the form `[gcd(x, y), a, b]`, where
  # `ax + by = gcd(x, y)`.
  #
  # @param [Integer] x
  # @param [Integer] y
  # @return [Array<Integer>]
  def gcdext(x, y)
    if x < 0
      g, a, b = gcdext(-x, y)
      return [g, -a, b]
    end
    if y < 0
      g, a, b = gcdext(x, -y)
      return [g, a, -b]
    end
    r0, r1 = x, y
    a0 = b1 = 1
    a1 = b0 = 0
    until r1.zero?
      q = r0 / r1
      r0, r1 = r1, r0 - q*r1
      a0, a1 = a1, a0 - q*a1
      b0, b1 = b1, b0 - q*b1
    end
    [r0, a0, b0]
  end

  # Returns the inverse of `num` modulo `mod`.
  #
  # @param [Integer] num the number
  # @param [Integer] mod the modulus
  # @return [Integer]
  # @raise ZeroDivisionError if the inverse of `base` does not exist
  def invert(num, mod)
    g, a, b = gcdext(num, mod)
    unless g == 1
      raise ZeroDivisionError.new("#{num} has no inverse modulo #{mod}")
    end
    a % mod
  end

  # Returns `base` raised to `exp` modulo `mod`.
  #
  # @param [Integer] base the base
  # @param [Integer] exp the exponent
  # @param [Integer] mod the modulus
  # @return [Integer]
  # @raise ZeroDivisionError if the `exp` is negative and the inverse
  #   of `base` does not exist
  def powmod(base, exp, mod)
    if exp < 0
      base = invert(base, mod)
      exp = -exp
    end
    result = 1
    multi = base % mod
    until exp.zero?
      result = (result * multi) % mod if exp.odd?
      exp >>= 1
      multi = (multi * multi) % mod
    end
    result
  end

end

I did not check the logic but tried several inputs and got expected output

Tom Lord
  • 27,404
  • 4
  • 50
  • 77
Tarek N. Elsamni
  • 1,718
  • 1
  • 12
  • 15