I have tested my SSH authentication using PuTTY with success, which I mean I can ssh to remote server using the private key provided. However, I am trying to use SCP function from Rcurl package in R, I got the error message saying:
Error in function (type, msg, asError = TRUE) : Authentication failure
Here is my code
r <- scp(host='eee.com', path = "/aaa/bbb/test.sas7bdat",
keypasswd = NA, user = "yyyyyy", rsa = TRUE,
key = "C:/Users/.ssh/authorized_keys", binary = NA)
C:/Users/.ssh/authorized_keys is my private RSA key.
the problem is that "key" must contain both the public and the private key. This should work:
r <- scp(host='eee.com', path = "/aaa/bbb/test.sas7bdat", keypasswd = NA, user = "yyyyyy", rsa = TRUE, key = c("C:/Users/.ssh/authorized_keys.pub","C:/Users/.ssh/authorized_keys"), binary = NA)
I have had the same problem and did not get scp to work, but found a workaround in getURLContent:
x <- getURLContent("sftp://path/file", .opts = list(
ssh.private.keyfile = "path/keyfile",
username="username",
keypasswd="password"))
And the private key should be an openSSH key (I had to convert my puttygen key) and while I had to download binary content I used getBinaryURL in the end with the same arguments.
Related
I'm trying to use the driver for R colab but it gives the following error
if (file.exists("/usr/local/lib/python3.6/dist-packages/google/colab/_ipython.py")) {
install.packages(" R.utils")
library("R.utils")
library("httr")
my_check <- function() {return(TRUE)}
reassignInPackage("is_interactive", pkgName = "httr", my_check)
options(rlang_interactive=TRUE )
}
drive_auth(
email = gargle:: gargle_oauth_email (),
path = NULL,
scopes = "https://www.googleapis.com/auth/drive",
cache = gargle:: gargle_oauth_cache (),
use_oob = gargle:: gargle_oob_default () ,
token = NULL
)
Error in drive_auth():
! Can't get Google credentials
ℹ Are you running googledrive in a non-interactive session? Consider:
• drive_deauth() to prevent the attempt to get credentials
• Call drive_auth() directly with all necessary specifics
ℹ See gargle's "Non-interactive auth" vignette for more details:
ℹ https://gargle.r-lib.org/articles/non-interactive-auth.html
Traceback:
drive_auth(use_oob = TRUE, cache = TRUE)
drive_abort(c("Can't get Google credentials", i = "Are you running googledrive in a non-interactive session? \\n Consider:",
. * = "{.fun drive_deauth} to prevent the attempt to get credentials",
. * = "Call {.fun drive_auth} directly with all necessary specifics",
. i = "See gargle's "Non-interactive auth" vignette for more details:",
. i = "{.url https://gargle.r-lib.org/articles/non-interactive-auth.html}"))
cli::cli_abort(message = message, ..., .envir = .envir)
rlang::abort(message, ..., call = call, use_cli_format = TRUE,
. .frame = .frame)
signal_abort(cnd, .file)
I did a Scopus search using rscopus package with the following code:
author_search(au_id = "Smith",
searcher = "affil(princeton) and authlast")
I got the following error:
Error in get_results(au_id, start = init_start, count = count, facets = facets, :
Unauthorized (HTTP 401).
However, this code works well:
scopus_search(query = "Vocabulary", max_count = 20,
count = 10)
I have set the Scopus API Key using options("elsevier_api_key" = "MY-API-KEY-HERE"). So, I wonder what the problem is.
I am trying to mock the output of a gh API request:
httptest2::with_mock_dir("gh", {
test_that("api works", {
gh::gh("GET /repos/r-lib/gh")
})
})
I am trying to set up testing for custom functions that routinely make API calls to GitHub and I am using gh to make these requests. I am following this tutorial as guidance: https://books.ropensci.org/http-testing/
However, no directory is created when this function is run. Is there anyway to capture the output of gh::gh and store it as a mock API return so that I can run my tests without needing GitHub authentication or even an internet connection?
httptest2 is specifically designed to test httr2 requests:
This package helps with writing tests for packages that use httr2
Unfortunately, gh uses httr:
Imports:
cli (>= 3.0.1),
gitcreds,
httr (>= 1.2),
ini,
jsonlite
This means that you can't directly use httptest2 with gh.
However, using gh source code, you can extract the parameters of the GET request sent to httr by gh:
gh_get <- function(endpoint, ..., per_page = NULL, .token = NULL, .destfile = NULL,
.overwrite = FALSE, .api_url = NULL, .method = "GET",
.limit = NULL, .accept = "application/vnd.github.v3+json",
.send_headers = NULL, .progress = TRUE, .params = list()) {
params <- c(list(...), .params)
params <- gh:::drop_named_nulls(params)
if (is.null(per_page)) {
if (!is.null(.limit)) {
per_page <- max(min(.limit, 100), 1)
}
}
if (!is.null(per_page)) {
params <- c(params, list(per_page = per_page))
}
req <- gh:::gh_build_request(
endpoint = endpoint, params = params,
token = .token, destfile = .destfile,
overwrite = .overwrite, accept = .accept,
send_headers = .send_headers,
api_url = .api_url, method = .method
)
req
}
req <- gh_get("GET /repos/r-lib/gh")
req
#$method
#[1] "GET"
#$url
#[1] "https://api.github.com/repos/r-lib/gh"
#$headers
# User-Agent Accept
# "https://github.com/r-lib/gh" "application/vnd.github.v3+json"
#$query
#NULL
#$body
#NULL
#$dest
#<request>
#Output: write_memory
This allows with the example you provided to use httr2 to send the same request :
library(httr2)
resp_httr2 <- request(base_url=req$url) %>%
req_perform() %>%
resp_body_json()
If you are mainly interested in json content, the results are the same, only the attributes differ :
resp_gh <- gh::gh("GET /repos/r-lib/gh")
all.equal(resp_gh,resp_httr2,check.attributes=FALSE)
#[1] TRUE
If you want to use httptest2, switching to httr2 would work:
with_mock_dir("gh", {
test_that("api works", {
resp <- request(base_url=req$url) %>%
req_perform() %>%
resp_body_json()
expect_equal(resp$full_name,"r-lib/gh")})
})
#Test passed 🎉
#[1] TRUE
Offline testing now works because gh\api.github.com directory was created by httptest2.
Maybe you can take inspiration from tests/testthat/test-mock-repos.R
res <- gh(
TMPL("/repos/{owner}/{repo}"),
owner = "gh-testing",
repo = test_repo,
.token = tt()
)
expect_equal(res$name, test_repo)
expect_equal(res$description, "Test repo for gh")
expect_equal(res$homepage, "https://github.com/r-lib/gh")
expect_false(res$private)
expect_false(res$has_issues)
expect_false(res$has_wiki)
A GET method would not create any directory.
I'm trying to use the httr R package to place orders on BitMex through their API.
I found some guidance over here, and after specifying both my API key and secret in respectively the objects K and S, I've tried the following
verb <- 'POST'
expires <- floor(as.numeric(Sys.time() + 10000))
path <- '/api/v1/order'
data <- '{"symbol":"XBTUSD","price":4500,"orderQty":10}'
body <- paste0(verb, path, expires, data)
signature <- hmac(S, body, algo = 'sha256')
body_l <- list(verb = verb, expires = expires, path = path, data = data)
And then both:
msg <- POST('https://www.bitmex.com/api/v1/order', encode = 'json', body = body_l, add_headers('api-key' = K, 'api-signature' = signature, 'api-expires' = expires))
and:
msg <- POST('https://www.bitmex.com/api/v1/order', body = body, add_headers('api-key' = K, 'api-signature' = signature, 'api-expires' = expires))
Give me the same error message when checked:
rawToChar(msg$content)
[1] "{\"error\":{\"message\":\"Signature not valid.\",\"name\":\"HTTPError\"}}"
I've tried to set it up according to how BitMex explains to use their API, but I appear to be missing something. They list out a couple of issues that might underly my invalid signature issue, but they don't seem to help me out. When following their example I get the exact same hashes, so that seems to be in order.
bit late to the party here but hopefully this helps!
Your POST call just needs some minor changes:
add content_type_json()
include .headers = c('the headers') in add_headers(). See example below:
library(httr)
library(digest)
S <- "your api secret"
K <- "your api key"
verb <- 'POST'
expires <- floor(as.numeric(Sys.time() + 10))
path <- '/api/v1/order'
data <- '{"symbol":"XBTUSD","price":4500,"orderQty":10}'
body <- paste0(verb, path, expires, data)
signature <- hmac(S, body, algo = 'sha256')
msg <- POST('https://www.bitmex.com/api/v1/order',
encode = 'json',
body = data,
content_type_json(),
add_headers(.headers = c('api-key' = K,
'api-signature' = signature,
'api-expires' = expires)))
content(msg, "text")
I have a package on CRAN - bitmexr - that provides a wrapper around the majority of BitMEX's API endpoints that you might be interested in. Still quite a "young" package so I would welcome any feedback!
SO I am using the R PKI package, thanks to Simon Urbanek, and am trying to understand the application of signing a message.
So I can figure out how to sign something.
require(PKI)
# generate 2048-bit RSA key
key <- PKI.genRSAkey(bits = 2048L)
# extract private and public parts as PEM
priv.pem <- PKI.save.key(key)
pub.pem <- PKI.save.key(key, private=FALSE)
# load back the public key separately
pub.k <- PKI.load.key(pub.pem)
# encrypt with the public key
x <- PKI.encrypt(charToRaw("Hello, world!"), pub.k)
# decrypt with private key
rawToChar(PKI.decrypt(x, key))
# So straight from the Package examples I have the public and private keys.
# Additionally, with the same I can sign a message
x <- charToRaw("My message to sign")
sig <- PKI.sign(x, key)
PKI.verify(x, sig, key)
# Now a slight change from the exapmles I will verify that the public key can verify
PKI.verify(x, sig, pub.k)
pub.pem can be written to a file as
PuK<-paste(pub.pem, collapse="")
and can later be reconstructed via
pub.pem<-substring(PuK,
c(1, 27, 91, 155, 219, 283, 347, 411, 419),
c(26, 90,154,218,282,346,410,418,442))
pub.k <- PKI.load.key(pub.pem)
and then verified again as
PKI.verify(x, sig, pub.k)
However, sig is raw
str(sig)
and when it is written to a file you get
sig<-paste(sig, collapse=" " )
but you can no longer verify the signature as it is now a string and not raw and charToRaw does not recreate the original signature. I can get part of the way there but not to get a correctly formatted raw vector to verify the signature
sigraw<-rawToChar(sig2, multiple = TRUE)
str(sapply(sigraw, FUN=charToRaw))
So is there a way I can write the signature to a file and then back again to verify a signature?
Not sure this is the most direct answer to the question but it does allow for a text sting that can be written to file and then reformatted.
library("BMS")
library("PKI")
library("pack")
# generate 2048-bit RSA key
key <- PKI.genRSAkey(bits = 2048L)
# extract private and public parts as PEM
priv.pem <- PKI.save.key(key)
pub.pem <- PKI.save.key(key, private=FALSE)
# load back the public key separately
pub.k <- PKI.load.key(pub.pem)
x <- charToRaw("My message to sign")
sig <- PKI.sign(x, key)
PKI.verify(x, sig, key)
bits<-rawToBits(sig)
### This part can be skipped, long way to make character vector & back ###
pbitsb<-paste(bits)
back<-sapply(pbitsb, FUN=as.raw)
back==bits
sigbits<-packBits(bits, type="raw")
sigback<-packBits(back, type="raw")
sig==sigbits&sigbits==sigback
PKI.verify(x,sigback,key)
#Can make this more compressed character vector
hexsig<-bin2hex(as.numeric(bits))
#This is the value to be shared in a text file as proof of signature
#The remaineder needs to be executed by the recipient
binsig<-hex2bin(hexsig)
backbin<-sapply(binsig, FUN=as.raw)
sigbin<-packBits(backbin, type="raw")
PKI.verify(x,sigbin,key)
sig==sigbits&sigbits==sigback&sigback==sigbin