1#' Signatures 2#' 3#' Sign and verify a message digest. RSA supports both MD5 and SHA signatures 4#' whereas DSA and EC keys only support SHA. ED25591 can sign any payload so you can 5#' set `hash` to `NULL` to sign the raw input data. 6#' 7#' The \code{ecdsa_parse} and \code{ecdsa_write} functions convert (EC)DSA signatures 8#' between the conventional DER format and the raw \code{(r,s)} bignum pair. Most 9#' users won't need this, it is mostly here to support the JWT format (which does not 10#' use DER). 11#' 12#' @export 13#' @rdname signatures 14#' @param data raw data vector or file path for message to be signed. 15#' If \code{hash == NULL} then \code{data} must be a hash string or raw vector. 16#' @param hash the digest function to use. Must be one of \code{\link{md5}}, 17#' \code{\link{sha1}}, \code{\link{sha256}}, \code{\link{sha512}} or \code{NULL}. 18#' @param key private key or file path. See \code{\link{read_key}}. 19#' @param pubkey public key or file path. See \code{\link{read_pubkey}}. 20#' @param sig raw vector or file path for the signature data. 21#' @param password string or a function to read protected keys. See \code{\link{read_key}}. 22#' @examples # Generate a keypair 23#' key <- rsa_keygen() 24#' pubkey <- key$pubkey 25#' 26#' # Sign a file 27#' data <- system.file("DESCRIPTION") 28#' sig <- signature_create(data, key = key) 29#' stopifnot(signature_verify(data, sig, pubkey = pubkey)) 30#' 31#' # Sign raw data 32#' data <- serialize(iris, NULL) 33#' sig <- signature_create(data, sha256, key = key) 34#' stopifnot(signature_verify(data, sig, sha256, pubkey = pubkey)) 35#' 36#' # Sign a hash 37#' md <- md5(data) 38#' sig <- signature_create(md, hash = NULL, key = key) 39#' stopifnot(signature_verify(md, sig, hash = NULL, pubkey = pubkey)) 40signature_create <- function(data, hash = sha1, key = my_key(), password = askpass){ 41 data <- path_or_raw(data) 42 sk <- read_key(key, password = password) 43 md <- if(is.null(hash)) parse_hash(data) else hash(data) 44 if(inherits(sk, "ed25519")) 45 return(data_sign(md, sk)) 46 if(!is.raw(md) || !(length(md) %in% c(16, 20, 28, 32, 48, 64))) 47 stop("data must be md5, sha1, or sha2 digest") 48 hash_sign(md, sk) 49} 50 51#' @export 52#' @rdname signatures 53signature_verify <- function(data, sig, hash = sha1, pubkey = my_pubkey()){ 54 data <- path_or_raw(data) 55 sig <- path_or_raw(sig) 56 pk <- read_pubkey(pubkey) 57 md <- if(is.null(hash)) parse_hash(data) else hash(data) 58 if(inherits(pk, "ed25519")) 59 return(data_verify(md, sig, pk)) 60 if(!is.raw(md) || !(length(md) %in% c(16, 20, 28, 32, 48, 64))) 61 stop("data must be md5, sha1, or sha2 digest") 62 hash_verify(md, sig, pk) 63} 64 65#' @export 66#' @rdname signatures 67#' @useDynLib openssl R_parse_ecdsa 68#' @examples # 69#' # ECDSA example 70#' data <- serialize(iris, NULL) 71#' key <- ec_keygen() 72#' pubkey <- key$pubkey 73#' sig <- signature_create(data, sha256, key = key) 74#' stopifnot(signature_verify(data, sig, sha256, pubkey = pubkey)) 75#' 76#' # Convert signature to (r, s) parameters and then back 77#' params <- ecdsa_parse(sig) 78#' out <- ecdsa_write(params$r, params$s) 79#' identical(sig, out) 80ecdsa_parse <- function(sig){ 81 if(length(sig) > 150) 82 warning("You can only parse DSA and ECDSA signatures. This looks like an RSA signature.") 83 .Call(R_parse_ecdsa, sig) 84} 85 86#' @export 87#' @rdname signatures 88#' @useDynLib openssl R_write_ecdsa 89#' @param r bignum value for r parameter 90#' @param s bignum value for s parameter 91ecdsa_write <- function(r, s){ 92 stopifnot(is.raw(r), is.raw(s)) 93 class(r) <- "bignum" 94 class(s) <- "bignum" 95 .Call(R_write_ecdsa, r, s) 96} 97 98#' @useDynLib openssl R_hash_sign 99hash_sign <- function(hash, key){ 100 .Call(R_hash_sign, hash, key) 101} 102 103#' @useDynLib openssl R_hash_verify 104hash_verify <- function(hash, sig, pubkey){ 105 .Call(R_hash_verify, hash, sig, pubkey) 106} 107