# R/paillier.R In homomorpheR: Homomorphic Computations in R

#' Construct a Paillier public key with the given modulus.
#' @docType class
#' @seealso \code{PaillierPrivateKey} which goes hand-in-hand with this object
#' @importFrom R6 R6Class
#' @importFrom gmp mod.bigz
#' @importFrom gmp mul.bigz
#' @importFrom gmp powm
#' @importFrom gmp as.bigz
#' @field bits the number of bits in the modulus
#' @field n the modulus
#' @field nSquared the square of the modulus
#' @field nPlusOne one more than the modulus
#' @section Methods:
#' \describe{
#'   \item{\code{PaillierPublicKey$new(bits, n)}}{Create a new public key with given \code{bits} and modulus #' \code{n}. It also precomputes a few values for more efficient computations} #' \item{\code{PaillierPublicKey$encrypt(m)}}{Encrypt a message. The value \code{m} should be less than
#'         the modulus, not checked}
#'   \item{\code{PaillierPublicKey$add(a, b)}}{Return the sum of two encrypted messages \code{a} and \code{b}} #' \item{\code{PaillierPublicKey$mult(a, b)}}{Return the product of two encrypted messages \code{a} and
#'              \code{b}}
#' }
#'
#' @export
#' @format An \code{\link{R6Class}} generator object

PaillierPublicKey <- R6Class("PaillierPublicKey",
private = list(
randomize = function(a) {
repeat {
r <- random.bigz(nBits = self$bits) ## make sure r <= n if (r < self$n)
break
}
rn <- powm(r, self$n, self$nSquared)
mod.bigz(mul.bigz(a, rn), self$nSquared) }), public = list ( ## fields bits = NULL, n = NULL, nSquared = NULL, nPlusOne = NULL, ## methods initialize = function(bits, n) { ## bits self$bits <- bits
## n
self$n <- n ## n squared self$nSquared <- mul.bigz(n, n)
## n plus 1
self$nPlusOne <- add.bigz(n, ONE) }, encrypt = function(m) { private$randomize(
mod.bigz(
mul.bigz(self$n, m), ONE), self$nSquared))
},
mod.bigz(mul.bigz(a, b), self$nSquared) }, mult = function(a, b) { powm(a, b, self$nSquared)
})
)

#' Construct a Paillier private key with the given secret and a public key
#' @docType class
#' @seealso \code{PaillierPublicKey} which goes hand-in-hand with this object
#' @importFrom R6 R6Class
#' @importFrom gmp mod.bigz
#' @importFrom gmp mul.bigz
#' @importFrom gmp div.bigz
#' @importFrom gmp sub.bigz
#' @importFrom gmp powm
#' @importFrom gmp inv.bigz
#' @importFrom gmp as.bigz
#' @field pubkey the Paillier public key
#'
#' @section Methods:
#' \describe{
#'   \item{\code{PaillierPrivateKey$new(lambda, pubkey)}}{Create a new private key with given secret #' \code{lambda} and the public key} #' \item{\code{PaillierPrivateKey$getLambda()}}{Return the secret \code{lambda}}
#'   \item{\code{PaillierPrivateKey$decrypt(c)}}{Decrypt a message. The value \code{c} should be an #' encrypted value} #' } #' #' @export #' @format An \code{\link{R6Class}} generator object PaillierPrivateKey <- R6Class("PaillierPrivateKey", private = list( lambda = NA, ## cached value for decryption x = NA ), public = list( ## fields pubkey = NULL, ## methods initialize = function(lambda, pubkey) { ## lambda private$lambda <- lambda
self$pubkey <- pubkey ## x (cached) for decryption private$x <- inv.bigz(
div.bigz(
sub.bigz(
powm(pubkey$nPlusOne, private$lambda, pubkey$nSquared), ONE), pubkey$n),
pubkey$n) }, getLambda = function() { private$lambda
},
decrypt = function(c) {
mod.bigz(
mul.bigz(
div.bigz(
sub.bigz(
powm(c, private$lambda, self$pubkey$nSquared), ONE), self$pubkey$n), private$x),
self$pubkey$n)
})
)

#' Construct a Paillier public and private key pair given a fixed number of bits
#' @docType class
#' @seealso \code{PaillierPublicKey} and \code{PaillierPrivateKey}
#' @importFrom R6 R6Class
#' @importFrom gmp sub.bigz
#' @importFrom gmp mod.bigz
#' @importFrom gmp mul.bigz
#' @importFrom gmp powm
#' @importFrom gmp isprime
#' @importFrom gmp sizeinbase
#' @importFrom gmp lcm.bigz
#' @importFrom gmp as.bigz
#' @field pubkey the Paillier public key
#'
#' @section Methods:
#' \describe{
#'   \item{\code{PaillierKeyPair$new(modulusBits)}}{Create a new private key with specified #' number of modulus bits} #' \item{\code{PaillierKeyPair$getPrivateKey()}}{Return the private key}
#' }
#'
#' @examples
#' keys <- PaillierKeyPair$new(1024) #' keys$pubkey
#' keys$getPrivateKey() #' #' @export #' @format An \code{\link{R6Class}} generator object PaillierKeyPair <- R6Class("PaillierKeyPair", private = list( privkey = NULL ), public = list( ## fields pubkey = NULL, ## methods initialize = function(modulusBits) { repeat { repeat { p <- random.bigz(nBits = modulusBits %/% 2) if (isprime(n = p, reps = 10)) break } repeat { q <- random.bigz(nBits = modulusBits %/% 2) if (isprime(n = q, reps = 10)) break } n <- mul.bigz(p, q) if ( ( p != q ) && ( sizeinbase(a = n, b = 2) == modulusBits) ) break } pubkey <- PaillierPublicKey$new(modulusBits, n)
self$pubkey <- pubkey lambda <- lcm.bigz(sub.bigz(p, ONE), sub.bigz(q, ONE)) private$privkey <- PaillierPrivateKey$new(lambda, pubkey) }, getPrivateKey = function() { private$privkey
})
)


## Try the homomorpheR package in your browser

Any scripts or data that you put into this service are public.

homomorpheR documentation built on May 29, 2017, 10:04 a.m.