Nothing
#' Creation of a private key
#'
#' Returns a random 256-bit private key in hex notation.
#'
#' @return \code{character}.
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Wallet_import_format},\cr
#' \url{https://en.bitcoin.it/wiki/Address}
#' @name createPrivateKey
#' @aliases createPrivateKey
#' @rdname createPrivateKey
#' @examples
#' suppressWarnings(RNGversion("3.5.0"))
#' createPrivateKey()
#' @export
createPrivateKey <- function(){
warning(paste0("\nFor exemplary purposes, only.\n",
"Use at your own risk!\n"))
s <- "0123456789ABCDEF"
idx <- sample(1:16, 64, replace = TRUE)
pk <- sapply(idx, function(x) substr(s, x, x))
pk <- paste(pk, collapse = "")
pk
}
#' Create WIF from a private key
#'
#' Returns the corresponding WIF key from a private key
#'
#' @param privkey \code{character}, a private key.
#' @param mainnet \code{logical}, whether the WIF should correspond
#' to the mainnet or testnet.
#'
#' @return \code{character}, the WIF key
#'
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Wallet_import_format},\cr
#' \url{https://en.bitcoin.it/wiki/Address}
#' @name PrivKey2Wif
#' @aliases PrivKey2Wif
#' @rdname PrivKey2Wif
#' @examples
#' suppressWarnings(RNGversion("3.5.0"))
#' pk <- createPrivateKey()
#' PrivKey2Wif(pk)
#' @export
PrivKey2Wif <- function(privkey, mainnet = TRUE){
warning(paste0("\nFor exemplary purposes, only.\n",
"Use at your own risk!\n"))
if (mainnet){
pke <- paste0("80", privkey)
} else {
pke <- paste0("EF", privkey)
}
privkeyext <- decodeHex(pke)
privkeyexth <- hash256(privkeyext)
checksum <- privkeyexth[1:4]
privkeyextcs <- c(privkeyext, checksum)
base58CheckEncode(privkeyextcs)
}
#' Create private key from WIF
#'
#' Returns the corresponding private key from a WIF key.
#'
#' @param wif \code{character}, a WIF key.
#'
#' @return \code{character}, the corresponding private key.
#'
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Wallet_import_format},\cr
#' \url{https://en.bitcoin.it/wiki/Address}
#' @name Wif2PrivKey
#' @aliases Wif2PrivKey
#' @rdname Wif2PrivKey
#' @examples
#' suppressWarnings(RNGversion("3.5.0"))
#' pk1 <- createPrivateKey()
#' wif <- PrivKey2Wif(pk1)
#' pk2 <- Wif2PrivKey(wif)
#' identical(pk1, pk2)
#' @export
Wif2PrivKey <- function(wif){
warning(paste0("\nFor exemplary purposes, only.\n",
"Use at your own risk!\n"))
fc <- substr(wif, 1, 1)
if (!(fc %in% c("5", "9"))){
msg <- paste0("First character in WIF does neither\n",
"correspond to mainnet nor testnet.\n")
stop(msg)
}
if (!identical(nchar(wif), 51L)){
stop("WIF must have a length of 51 characters.\n")
}
bytestring <- base58CheckDecode(wif)
n <- length(bytestring) - 4L
bytestringshort <- bytestring[1:n]
privkey <- bytestringshort[-1]
toupper(paste0(privkey, collapse = ""))
}
#' Create public key from private key
#'
#' This function creates the 512-bit public key corresponding
#' to a private key.
#'
#' @param privkey \code{character}, the private key.
#' @param mainnet \code{logical}, whether the WIF should correspond
#' to the mainnet or testnet.
#'
#' @return \code{character}, the public key.
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Address}
#' @name PrivKey2PubKey
#' @aliases PrivKey2PubKey
#' @rdname PrivKey2PubKey
#' @export
PrivKey2PubKey <- function(privkey, mainnet = TRUE){
warning(paste0("\nFor exemplary purposes, only.\n",
"Use at your own risk!\n"))
pk <- paste0("0x", privkey, collapse = "")
pk <- gmp::as.bigz(pk)
p <- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"
b <- "0x0000000000000000000000000000000000000000000000000000000000000007"
a <- "0x0000000000000000000000000000000000000000000000000000000000000000"
r <- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"
Gx <- "0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
Gy <- "0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"
ec <- ecparam(p, a, b)
g <- ecpoint(ec, gmp::as.bigz(Gx), gmp::as.bigz(Gy), gmp::as.bigz(r))
ans <- g * pk
x <- as.character(ans@x, b = 16)
y <- as.character(ans@y, b = 16)
toupper(paste0("04", x, y, collapse = ""))
}
#' Create public key hash from 512-bit public key
#'
#' This function returns the associated public key hash
#' from a 512-bit public key by using the \code{hash160()} function.
#'
#' @param pubkey \code{character}, the public key.
#' @param mainnet \code{logical}, whether the WIF should correspond
#' to the mainnet or testnet.
#'
#' @return \code{character}, the hash of a public key
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Address}
#' @name PubKey2PubHash
#' @aliases PubKey2PubHash
#' @rdname PubKey2PubHash
#' @export
PubKey2PubHash <- function(pubkey, mainnet = TRUE){
warning(paste0("\nFor exemplary purposes, only.\n",
"Use at your own risk!\n"))
pubkey160 <- hash160(decodeHex(pubkey))
checksum <- pubkey160[1:4]
if (mainnet){
pubkey160ext <- c(decodeHex("00"), pubkey160)
} else {
pubkey160ext <- c(decodeHex("6f"), pubkey160)
}
pubkey160extcs <- c(pubkey160ext, checksum)
toupper(paste0(pubkey160extcs,
collapse = "")
)
}
#' Create BTC address from public key hash
#'
#' This function returns the corresponding BTC address from a
#' hashed public key.
#'
#' @param pubhash \code{character}, the public key hash.
#'
#' @return \code{character}, the BTC address
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Address}
#' @name PubHash2BtcAdr
#' @aliases PubHash2BtcAdr
#' @rdname PubHash2BtcAdr
#' @export
PubHash2BtcAdr <- function(pubhash){
warning(paste0("\nFor exemplary purposes, only.\n",
"Use at your own risk!\n"))
pubhashhex <- decodeHex(pubhash)
base58CheckEncode(pubhashhex)
}
#' Create BTC addresses
#'
#' This function creates an object of S4-class \code{BTCADR}.
#'
#' @param privkey \code{character}, a private key.
#' @param mainnet \code{logical}, for which net the keys should belong to.
#'
#' @return Object of S4-class \code{BTCADR}
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Address}
#' @name createBtcAdr
#' @aliases createBtcAdr
#' @rdname createBtcAdr
#' @export
createBtcAdr <- function (privkey, mainnet = TRUE) {
warning(paste0("\nFor exemplary purposes, only.\n",
"Use at your own risk!\n"))
pk <- sapply(seq(1, nchar(privkey), by = 2), function(x) substr(privkey,
x, x + 1))
if (mainnet) {
pke <- c("80", pk)
}
else {
pke <- c("ef", pk)
}
pke <- as.raw(strtoi(pke, base = 16L))
h <- hash256(pke)
checksum <- h[1:4]
pkecs <- c(pke, checksum)
wif <- base58CheckEncode(pkecs)
pubkey <- PrivKey2PubKey(privkey)
pub160 <- hash160(decodeHex(pubkey))
if (mainnet) {
pub160e <- c(decodeHex("00"), pub160)
}
else {
pub160e <- c(decodeHex("6f"), pub160)
}
cs <- hash256(pub160e)[1:4]
pubhash <- c(pub160e, cs)
btcadr <- base58CheckEncode(pubhash)
new("BTCADR", privkey = privkey, wif = wif, pubkey = pubkey,
pubhash = toupper(paste(pubhash, collapse = "")), btcadr = btcadr,
mainnet = mainnet)
}
#' Decoding of a hex string
#'
#' This function converts a hex string,, whereby the string must not
#' contain the \code{0x} prefix, to a \code{list} object with the associated
#' integers as its elements.
#'
#' @param s \code{character}, the hex string.
#'
#' @return \code{list}
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Wallet_import_format},\cr
#' \url{https://en.bitcoin.it/wiki/Address}
#' @name decodeHex
#' @aliases decodeHex
#' @rdname decodeHex
#' @examples
#' suppressWarnings(RNGversion("3.5.0"))
#' pk <- createPrivateKey()
#' decodeHex(pk)
#' @export
decodeHex <- function(s){
h <- sapply(seq(1, nchar(s), by = 2), function(x) substr(s, x, x + 1))
ans <- as.raw(strtoi(h, base = 16L))
ans
}
#' Concatenate two hex strings
#'
#' This function concatenates two hex strings, provided without the \code{0x} prefix,
#' and returns a \code{list} object of the associated
#' integers.
#'
#' @param hex1 \code{character}, a hex string.
#' @param hex2 \code{character}, a hex string.
#' @return \code{list}
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Wallet_import_format},\cr
#' \url{https://en.bitcoin.it/wiki/Address}
#' @name concatHex
#' @aliases concatHex
#' @rdname concatHex
#' @examples
#' suppressWarnings(RNGversion("3.5.0"))
#' h1 <- "80"
#' h2 <- createPrivateKey()
#' concatHex(h1, h2)
#' @export
concatHex <- function(hex1, hex2){
h1 <- decodeHex(hex1)
h2 <- decodeHex(hex2)
ans <- c(h1, h2)
ans
}
#' Base 58 binary-to-text-encoding
#'
#' This is a modified binary-to-text encoding used
#' for encoding Bitcoin addresses, aka \emph{Base58Check}.
#' If this is applied to an extended private key with its trailing
#' check sum, then the result is the \emph{Wallet Import Format},
#' (WIF).
#'
#' @param x \code{character}, string in hex format.
#'
#' @return \code{character}, the encoded string.
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Wallet_import_format},\cr
#' \url{https://en.bitcoin.it/wiki/Address},\cr
#' \url{https://en.bitcoin.it/wiki/Base58Check_encoding}
#' @name base58CheckEncode
#' @aliases base58CheckEncode
#' @rdname base58CheckEncode
#' @export
base58CheckEncode <- function(x){
b58 <- "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
zerohex <- as.raw(strtoi("", base = 16L))
countzero <- which(x == zerohex)
xchar <- paste0("0x", paste(x, collapse = ""))
ben <- gmp::as.bigz(xchar)
ans <- ""
while (ben > 0){
idx <- ben %% 58L ## remainder
ans <- paste0(substr(b58, idx + 1, idx + 1), ans) ## reverse order
ben <- ben %/% 58L
}
if (length(countzero) > 0){
ans <- paste(c(rep("1", countzero), ans), collapse = "")
}
ans
}
#' Base 58 binary-to-text-decoding
#'
#' This is a modified binary-to-text decoding used
#' for decoding Bitcoin addresses, aka \emph{Base58Check}.
#' If this is applied to a WIF address and the first and last four
#' bytes are dropped, the result is the corresponding private key.
#'
#' @param x \code{character}, string in hex format.
#'
#' @return \code{list}, the decoded elements of the string.
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Wallet_import_format},\cr
#' \url{https://en.bitcoin.it/wiki/Address},\cr
#' \url{https://en.bitcoin.it/wiki/Base58Check_encoding}
#' @name base58CheckDecode
#' @aliases base58CheckDecode
#' @rdname base58CheckDecode
#' @export
base58CheckDecode <- function(x){
b58 <- "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
b58v <- unlist(strsplit(b58, ""))
xv <- unlist(strsplit(x, ""))
ben <- 0L # big endian number
for (i in 1:nchar(x)){
## index starts at 1 not 0
ben <- gmp::as.bigz(ben * 58L + which(b58v == xv[i]) - 1.0)
}
shex <- ""
while (ben > 0){
ben %% 256L
h <- as.integer(ben %% 256L)
class(h) <- "hexmode"
h <- format(h, width = 2)
shex <- paste0(h, shex)
ben <- gmp::as.bigz(ben %/% 256L)
}
decodeHex(shex)
}
#' BTC hash256
#'
#' This function returns the hash by applying the \code{sha256} hashing
#' algorithm twice to a \code{raw} object.
#'
#' @param d \code{raw}, vector.
#'
#' @return \code{character}, the value of \code{d} hashed twice.
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Address}
#' @name hash256
#' @aliases hash256
#' @rdname hash256
#' @export
hash256 <- function(d){
if (!identical(class(d), "raw")){
msg <- paste0("Object 'd' is not of class raw.",
"\n",
"Trying to coerce from character.\n")
warning(msg)
d <- as.raw(strtoi(d, base = 16L))
}
d1 <- openssl::sha256(d)
d1 <- decodeHex(paste(d1, collapse = ":"))
d2 <- openssl::sha256(d1)
d2 <- decodeHex(paste(d2, collapse = ":"))
d2
}
#' BTC hash160
#'
#' This function returns the hash by applying the \code{sha256} hashing
#' first and then to the resulting hash the \code{ripemd160} algorithm.
#'
#' @param d \code{raw}, vector.
#'
#' @return \code{character}, the value of \code{d} hashed with
#' \code{sha256} and \code{ripemd160}.
#' @family BtcAdresses
#' @author Bernhard Pfaff
#' @references \url{https://en.bitcoin.it/wiki/Address}
#' @name hash160
#' @aliases hash160
#' @rdname hash160
#' @export
hash160 <- function(d){
if (!identical(class(d), "raw")){
msg <- paste0("Object 'd' is not of class raw.",
"\n",
"Trying to coerce from character.\n")
warning(msg)
d <- as.raw(strtoi(d, base = 16L))
}
d1 <- openssl::sha256(d)
d1 <- decodeHex(paste(d1, collapse = ":"))
d2 <- openssl::ripemd160(d1)
d2 <- decodeHex(paste(d2, collapse = ":"))
d2
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.