R/sign.R

#' Sign a transaction.
#' @description internal functions specific to the signing of transcations.
#' @references Some reference for the ed25519 algorithm: http://ed25519.cr.yp.to/
#' @note These functions were adapted from this gist by Johan Stén: https://gist.github.com/johansten/3859fb4f9a24a5b6fee5bef86a3ad91c

.sign <- function(sk, m) {
  h = .hash(sk)
  a = as.bigz(2) ** 254 + sum(do.call(c, lapply(3:253, function(i) {
    as.bigz(2) ** i * .bit(h, i)
  })))
  pk = .multiply_and_encode(a)
  half = rawToChar(h[33:64])
  r = .hint(paste0(half, m))
  rp = .multiply_and_encode(r)
  s = (r + .hint(paste0(rp, pk, m)) * a) %% global$l
  return(paste0(rp, .encode_int(s)))
}

.multiply_and_encode <- function(scalar) {
  x = .scalar_multiply(scalar)
  return(.encode_point(x[1], x[2]))
}

.scalar_multiply <- function(e) {
  mask = 0
  num_bits = 0

  while (e >= 1) {
    mask = .bitOr(mask * 2, .bitAnd(e, 1))
    if (e %% 2 == 1) {
      e = as.bigz((e - 1) / 2)
    } else {
      e = as.bigz(e / 2)
    }
    num_bits = num_bits + 1
  }

  x = 0
  y = 1
  z = 1

  for (n in 0:(num_bits - 1)) {
    result = .edwards_double(x, y, z)
    x = result[1]
    y = result[2]
    z = result[3]
    if (.bitAnd(mask, 1) > 0) {
      result = .edwards_add_b(x, y, z)
      x = result[1]
      y = result[2]
      z = result[3]
    }
    mask = .bitShiftR(mask, 1)
  }

  z_inv = .inv(z)
  x = .mult(x, z_inv)
  y = .mult(y, z_inv)
  return(c(x, y))
}

.encode_point <- function(x, y) {
  bits = sapply(0:254, function(i) {
    as.integer(.bitShiftR(y, i) %% 2)
  })
  bits[256] = as.integer(x %% 2)
  chrs = sapply(0:31, function(i) {
    rawToChar(as.raw(sum(sapply(0:7, function(j) {
      bitwShiftL(bits[(i * 8 + j) + 1], j)
    }))))
  })
  return(paste(chrs, collapse = ""))
}

.encode_int <- function(y) {
  bits = sapply(0:255, function(i) {
    as.integer(.bitShiftR(y, i) %% 2)
  })
  chrs = sapply(0:31, function(i) {
    rawToChar(as.raw(sum(sapply(0:7, function(j) {
      bitwShiftL(bits[(i * 8 + j) + 1], j)
    }))))
  })
  return(paste(chrs, collapse = ""))
}
froocpu/stellaR documentation built on May 17, 2019, 7:05 p.m.