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
Related
does anyone know any package that support the following conversion of base58 to hex string or the other way round from hex string to base58 encoding.
below is an example of a python implementation.
https://www.reddit.com/r/Tronix/comments/ja8khn/convert_my_address/
this hex string <- "4116cecf977b1ecc53eed37ee48c0ee58bcddbea5e"
should result in this : "TC3ockcvHNmt7uJ8f5k3be1QrZtMzE8MxK"
here is a link to be used for verification: https://tronscan.org/#/tools/tron-convert-tool
I was looking for it and I was able to design functions that produce the desired result.
import base58
def hex_to_base58(hex_string):
if hex_string[:2] in ["0x", "0X"]:
hex_string = "41" + hex_string[2:]
bytes_str = bytes.fromhex(hex_string)
base58_str = base58.b58encode_check(bytes_str)
return base58_str.decode("UTF-8")
def base58_to_hex(base58_string):
asc_string = base58.b58decode_check(base58_string)
return asc_string.hex().upper()
They are useful if you want to convert the public key (hex) of the transactions to the addresses of the wallets (base58).
public_key_hex = "0x4ab99740bdf786204e57c00677cf5bf8ee766476"
address = hex_to_base58(public_key_hex)
print(address)
# TGnKLLBQyCo6QF911j65ipBz5araDSYQAD
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!
I'm using slackr to send alert messages to a Slack channel. It works great except the message format is not great and I want to improve it.
install_github("hrbrmstr/slackr")
library(slackr)
slackr_setup(channel="#alerts", username="Mark Davis",
incoming_webhook_url = "https://hooks.slack.com/services/T31P8UDAB/BCH4HKQSC/*********",
api_token = "*********", echo = F)
alert="On Monday, 2018-09-03 # 2pm Pacific..."
slackr(alert)
Here is an example of how a message from slackr looks in Slack:
Here is an example of how I'd like it to look:
slackr doesn't seem to have many options in the way of formatting. I was thinking of building an image and inserting that, but I'm having trouble building an image out of a text file using R.
Perhaps there is another api I could call that could take my text and format it for slack?
I'm open to any suggestions.
Addendum:
Slackr has an option to upload files, so my latest attempt is to create an image from the text message and upload that object.
I am able to create a png file from the text message using the magick library. I created an image with a colored background, and I simply add the message text to the image:
library(magick)
alert_picture <- image_read('alert_480x150_dark_red.png')
alert_picture=image_annotate(alert_picture, DreamCloud_Alert, size = 20, gravity = "southwest",
color = "white", location = "+10+10")
image_write(alert_picture, path = "alert_picture.png", format = "png")
The image looks pretty good (although there doesn't seem to be an easy way to bold or underline specific words in the message), but the obstacle now is that I can't get the upload command to work.
slackr_upload(filename = "alert_picture.png")
I don't get any error messages but nothing is uploaded to slack.
I got around this issue by using the httr package to execute the post image function to slack.
Thanks to Adil B. for providing the solution:
Post Image to Slack Using HTTR package in R
I am not sure this is what you meant, but I solved allowing formatting like in a regular slack message by altering the slackr_bot() function and just removing the 2 sets of 3 back-ticks at the end of the code where it says text. Then just call it slackr_bot1() or something, and then you can post formatted messages. This is the function after the back-ticks removal:
slackr_bot1 <- function(...,
channel=Sys.getenv("SLACK_CHANNEL"),
username=Sys.getenv("SLACK_USERNAME"),
icon_emoji=Sys.getenv("SLACK_ICON_EMOJI"),
incoming_webhook_url=Sys.getenv("SLACK_INCOMING_URL_PREFIX")) {
if (incoming_webhook_url == "") {
stop("No incoming webhook URL specified. Did you forget to call slackr_setup()?", call. = FALSE)
}
if (icon_emoji != "") { icon_emoji <- sprintf(', "icon_emoji": "%s"', icon_emoji) }
resp_ret <- ""
if (!missing(...)) {
# mimics capture.output
# get the arglist
args <- substitute(list(...))[-1L]
# setup in-memory sink
rval <- NULL
fil <- textConnection("rval", "w", local = TRUE)
sink(fil)
on.exit({
sink()
close(fil)
})
# where we'll need to eval expressions
pf <- parent.frame()
# how we'll eval expressions
evalVis <- function(expr) withVisible(eval(expr, pf))
# for each expression
for (i in seq_along(args)) {
expr <- args[[i]]
# do something, note all the newlines...Slack ``` needs them
tmp <- switch(mode(expr),
# if it's actually an expresison, iterate over it
expression = {
cat(sprintf("> %s\n", deparse(expr)))
lapply(expr, evalVis)
},
# if it's a call or a name, eval, printing run output as if in console
call = ,
name = {
cat(sprintf("> %s\n", deparse(expr)))
list(evalVis(expr))
},
# if pretty much anything else (i.e. a bare value) just output it
integer = ,
double = ,
complex = ,
raw = ,
logical = ,
numeric = cat(sprintf("%s\n\n", as.character(expr))),
character = cat(sprintf("%s\n\n", expr)),
stop("mode of argument not handled at present by slackr"))
for (item in tmp) if (item$visible) { print(item$value, quote = FALSE); cat("\n") }
}
on.exit()
sink()
close(fil)
# combined all of them (rval is a character vector)
output <- paste0(rval, collapse="\n")
loc <- Sys.getlocale('LC_CTYPE')
Sys.setlocale('LC_CTYPE','C')
on.exit(Sys.setlocale("LC_CTYPE", loc))
resp <- POST(url = incoming_webhook_url, encode = "form",
add_headers(`Content-Type` = "application/x-www-form-urlencoded",
Accept = "*/*"), body = URLencode(sprintf("payload={\"channel\": \"%s\", \"username\": \"%s\", \"text\": \"%s\"%s}",
channel, username, output, icon_emoji)))
warn_for_status(resp)
}
return(invisible())
}
slackr_bot1("*test* on time")
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.
Little stuck on how to approach this question:
Xavier and Yvonne are in love. They both set up their own RSA keys:
Xavier’s public key is (eX , nX ) = (887, 15833), and Yvonne’s public key
is (eY , nY ) = (977, 13019). For each of the following, do not factor nX nor
nY , show the set up of the calculations and the results. You should use a
computer to perform the calculations.
(a) Yvonne wants to send Xavier a private message of love, which is
M = 3141. What is the ciphertext that Yvonne needs to send to Xavier?
(b) In return, Yvonne received three mysterious messages: C1 = 10889,
C2 = 2622, C3 = 4061. All three senders claim to be Xavier, and all
claim to have sent the message Ci ≡ MdX (mod nX) where M = 3141 and dX
is Xavier’s private key. However, only Xavier himself knows the actual
value of dX , and the other two are imposters trying to steal Yvonne away
from him. Help Yvonne determine which message is actually from Xavier,
and explain why your method works.
Any tips would be great thanks!
a) In order to send an RSA-encrypted message such that only the private key holder can decrypt it, it must be encrypted using the recipient's public key. In this case, the recipient is Xavier, so the message is encrypted using his public key: (eX, nX) = (887, 15833):
Message: M = 3141
Ciphertext: C = MeX mod nX
C = 3141887 mod 15833
C = 2054
b) This is essentially a signature verification of a message signed using Xavier's private key, which requires the use of the signer's public key. It is necessary to find which of the three messages, when decrypted using Xavier's public key results in the message that was sent (3141):
Ciphertext 1: C1 = 10889
Message 1: M1 = C1eX mod nX
M1 = 10889887 mod 15833
M1 = 6555 (mismatch)
Ciphertext 2: C2 = 2622
Message 2: M2 = C2eX mod nX
M2 = 2622887 mod 15833
M2 = 1466 (mismatch)
Ciphertext 3: C3 = 2622
Message 3: M3 = C3eX mod nX
M3 = 4061887 mod 15833
M3 = 3141 (match!)
Only C3 matches the message when decrypted using Xavier's public key, and so is the only authentic message.
Note: I used WolframAlpha to perform the modular exponentiation above, but it's easy enough (though rather more time-consuming) to do manually using repeated multiplication then reduction modulo n.