I'm trying to use the Bittrex API. The only example provided is the following. I'm not even sure what language this is. I'm trying to replicate this in bash. Full API detail is located here https://bittrex.com/Home/Api
$apikey='xxx';
$apisecret='xxx';
$nonce=time();
$uri='https://bittrex.com/api/v1.1/market/getopenorders?apikey='.$apikey.'&nonce='.$nonce;
$sign=hash_hmac('sha512',$uri,$apisecret);
$ch = curl_init($uri);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('apisign:'.$sign));
$execResult = curl_exec($ch);
$obj = json_decode($execResult);
I have tried several things but here is the latest I tried.
#Bash
apikey="mykey"
secret="mysecret"
nonce=`date +%s`
uri="https://bittrex.com/api/v1.1/market/getopenorders?apikey=$apikey&nonce=$nonce"
apisig=`echo -n "$uri" | openssl dgst -sha512 -hmac "$secret"`
curl -sG https://bittrex.com/api/v1.1/market/getopenorders?nonce="$nonce"&apikey="$apikey"&apisig="$apisig"
I get "{"success":false,"message":"APIKEY_NOT_PROVIDED","result":null}"
What you're missing are:
escaping & in query string
passing digest as header rather than parameter
So the code that worked for me is:
#!/bin/bash
apikey="mykey"
secret="mysecret"
nonce=`date +%s`
uri="https://bittrex.com/api/v1.1/market/getopenorders?apikey=$apikey&nonce=$nonce"
apisig=`printf %s "$uri" | openssl dgst -sha512 -hmac "$secret"| sed 's/^.*= //'`
curl -sG $uri --header "apisign: $apisig"
Related
hi guys i try to many day to run this code but returnme always code":-1022,"msg":"Signature for this request is not valid , but i am sure is correct a code , anyone can controll my script for see if is all ok ?? thanks at all for advice
APIKEY="MY APIKEY"
APISECRET="MY SECRET KEY"
URLPART2="symbol=BNBUSDT&side=BUY&type=LIMIT"eOrderQty=10&price=270.3&stopPrice=270.3&newOrderRespType=FULL"
RECVWINDOW=50000
RECVWINDOW="recvWindow=$RECVWINDOW"
TIMESTAMP="timestamp=$(( $(date +%s) *1000))"
QUERYSTRING="&$URLPART2&$RECVWINDOW&$TIMESTAMP"
SIGNATURE=$(echo -n "$QUERYSTRING" | openssl dgst -sha256 -hmac $APISECRET | cut -c 10-)
SIGNATURE="signature=$SIGNATURE"
#curl -s -H "X-MBX-APIKEY: $APIKEY" "https://api.binance.com/api/v3/order/test?$URLPART2&$RECVWINDOW&$TIMESTAMP&$SIGNATURE"
curl -H "X-MBX-APIKEY: $APIKEY" -X POST "https://api.binance.com/api/v3/order/test?$URLPART2&$RECVWINDOW&$TIMESTAMP&$SIGNATURE"
echo```
I am trying to use Hashicorp Vault to sign a file with RSASSA-PSS-4096. The file is too big for sending it to the server directly, so I want to prehash it locally and then send the digest via POST request to the Vault transit engine.
While the Vault signature verification works, the OpenSSL verification fails.
Please see my drafted script:
# Calculate SHA256 hash and convert to base64
sha256sum_base64=$(openssl dgst -sha256 -binary $1 | base64)
# Sign Hash Value with Vault
json_response=$(curl -s \
--header "X-Vault-Token: $(cat token)" \
--request POST \
--data-binary '{"input": "'"$sha256sum_base64"'", "prehashed": true, "signature_algorithm": "pss", "hash_algorithm": "sha2-256"}' \
http://127.0.0.1:8200/v1/transit/sign/rsa_4096)
# Extract base64 signature from the json response.
signature_base64=$(echo $json_response | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['signature'])" | cut -d ":" -f 3)
# Convert signature from base64 to binary and write to file
sigfile=$1__signature.bin
echo $signature_base64 | openssl base64 -d -A -in - -out $sigfile
# Check whether signature is valid via OpenSSL
echo "OpenSSL --> " $(openssl dgst -sha256 -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:32 -verify rsa_4096_pub.pem -signature $sigfile $1)
# Check whether signature is valid via Vault
signature_vaultformat="vault:v1:$signature_base64"
verify_response=$(curl -s \
--header "X-Vault-Token: $(cat token)" \
--request POST \
--data-binary '{"input": "'"$sha256sum_base64"'", "signature": "'"$signature_vaultformat"'", "prehashed": true, "signature_algorithm": "pss", "hash_algorithm": "sha2-256"}' \
http://127.0.0.1:8200/v1/transit/verify/rsa_4096)
echo "Vault Verify --> " $(echo $verify_response | python3 -c "import sys, json; print(json.load(sys.stdin)['data']['valid'])")
What could be the problem here? I played with rsa_pss_saltlen parameters (e.g. -1) without success. Is there another OpenSSL parameter I am missing? Do I need to consider something for EMSA-PSS?
Here is a proof-of-concept where you can sign a piece of text using the Transit secrets engine and then verify the signature using openssl rather than using the Transit secrets engine again.
# Define our plaintext
TEXT="abc123"
# Encode our plaintext with base64
B64_ENCODED_TEXT=$(echo $TEXT | base64)
# Reset the transit secrets engine
vault secrets disable transit
vault secrets enable transit
# Create a key called 'test' using 'rsa-2048'
vault write -f transit/keys/test \
type='rsa-2048'
# Export the public key from the transit secret engine key named 'test'
PUBLIC_KEY=$(vault read -format=json transit/keys/test | \
jq -r '.data.keys."1".public_key')
# Sign our base64 encoded text using our transit key named 'test' and
# capture the signature
SIGNATURE=$(vault write -format=json transit/sign/test/sha2-256 \
input="$B64_ENCODED_TEXT" \
signature_algorithm="pss" | \
jq -r '.data.signature')
# Demonstrate that we can use transit to verify our signature
printf "\nVerifying signature using Vault Transit...\n"
vault write transit/verify/test/sha2-256 \
signature_algorithm="pss" \
input=$B64_ENCODED_TEXT \
signature=$SIGNATURE
# Write out public key to a file
echo $PUBLIC_KEY > publickey.pem
# Remove the metadata from the Vault supplied signature and decode the
# signature using base64, writing the raw signature to a file
echo $SIGNATURE | cut -d':' -f3 | base64 -d > sig
# Write the non-encoded plaintext to a file
echo "$TEXT" > mytext
# Use openssl to verify the signature using the base64 decoded raw signature
# along with the public key and the non-encoded plaintext
printf "\nVerifying signature using openssl...\n"
openssl dgst \
-sha256 \
-verify publickey.pem \
-signature sig \
-sigopt rsa_padding_mode:pss \
mytext
Some important notes below:
Note that ALL data that is signed by Vault Transit secret engine must first be base64 encoded.
When using openssl to verify a signature, you must make sure that you are using the correct signature algorithm.
When Vault provides a signature, it's in the following format: vault:v1:8SDd3WHDOjf7mq69... where vault denotes that it was signed by Vault, v1 denotes the version of the key and the final part is the actual signature that is encoded using base64. The openssl utility requires that the signature is binary and not base64. In order to verify this signature with openssl, you must remove the first 2 parts of the Vault provided signature. You must then decode the base64 encoded signature and use the resultant binary signature when verifying with openssl.
When verifying with openssl you can not use use the base64 encoded version of the text, you must use the non-base64 encoded plaintext.
EDIT: The issue is that I'm using hex encoded strings as the keys and I should be using raw bytes. How can I get the raw bytes out of the openssl command?
--- Original question ---
I'm attempting to follow the instructions for creating a signed iam request found here: https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html.
It basically says to produce the signing key and signature you follow these steps:
signing key = HMAC(HMAC(HMAC(HMAC("AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY","20150830"),"us-east-1"),"iam"),"aws4_request")
signature = HexEncode(HMAC(signing key, "AWS4-HMAC-SHA256\n20150830T123600Z\n20150830/us-east-1/iam/aws4_request\nf536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59"))
I've created the following shell script as a test:
#!/usr/bin/env bash
set -euo pipefail
stringToSign="AWS4-HMAC-SHA256\n20150830T123600Z\n20150830/us-east-1/iam/aws4_request\nf536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59"
dateKey=$(echo -n "20150830" | openssl dgst -sha256 -hmac "AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY")
regionKey=$(echo -n "us-east-1" | openssl dgst -sha256 -hmac "$dateKey")
serviceKey=$(echo -n "iam" | openssl dgst -sha256 -hmac "$regionKey")
signingKey=$(echo -n "aws4_request" | openssl dgst -sha256 -hmac "$serviceKey")
echo "signing key: $signingKey"
signature=$(echo -n "$stringToSign" | openssl dgst -sha256 -hmac "$signingKey")
echo "signature: $signature"
The output is:
signing key: 8c028f7953b7f2b9fa6d2e816f7b15675dc2329c139e293b383759c5ba8af679
signature: 9fd29d6aaac30d0747da90c23a4b883a8bc02b439f35df255fa2f93f6c99f46f
dateKey is 45fb073b035485bb42f64d8d242984f3431d02e31c35ba4b661d31bbec45378d
However the document linked above says that it should be:
signing key: c4afb1cc5771d871763a393e44b703571b55cc28424d1a5e86da6ed3c154a4b9
signature: 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7
How can I produce the correct key and signature?
EDIT -- openssl version:
$ openssl version -a
LibreSSL 2.6.5
built on: date not available
platform: information not available
options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: information not available
OPENSSLDIR: "/private/etc/ssl"
How can I get the raw bytes out of the openssl command?
Use -binary option. From manpage for openssl dgst:
openssl dgst [-cd] [-binary] [-digest] [-hex] [-hmac key] ...
-binary
Output the digest or signature in binary form.
To get the correct signature, I also had to replace the \n characters in the string to sign with actual newline characters.
Working script:
#!/usr/bin/env bash
set -euo pipefail
stringToSign="AWS4-HMAC-SHA256
20150830T123600Z
20150830/us-east-1/iam/aws4_request
f536975d06c0309214f805bb90ccff089219ecd68b2577efef23edd43b7e1a59"
dateKey=$(echo -n "20150830" | openssl dgst -sha256 -binary -hmac "AWS4wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY")
regionKey=$(echo -n "us-east-1" | openssl dgst -sha256 -binary -hmac "$dateKey")
serviceKey=$(echo -n "iam" | openssl dgst -sha256 -binary -hmac "$regionKey")
signingKey=$(echo -n "aws4_request" | openssl dgst -sha256 -binary -hmac "$serviceKey")
signature=$(echo -n "$stringToSign" | openssl dgst -sha256 -hmac "$signingKey")
echo "signature: $signature"
# signature: 5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7
I try to create a file share on an existing Azure storage account via bash script. I only have the account name and key, but don't want to use login credentials.
This is what I have so far:
#!/bin/sh
DATE_ISO=$(date +"%Y-%m-%dT%H:%M:%S")
VERSION="2015-02-21"
curl --header "x-ms-version: ${VERSION}" --header "x-ms-date: ${DATE_ISO}" --header "Authorization: SharedKey mystorageaccount:?????" https://mystorageaccount.file.core.windows.net/myshare?restype=share
The documentation says, "Authorization" is required (syntax: Authorization="[SharedKey|SharedKeyLite] <AccountName>:<Signature>") and "Signature" is a Hash-based Message Authentication Code (HMAC) constructed from the request and computed by using the SHA256 algorithm, and then encoded by using Base64 encoding.
So how do I generate this Signature?
Try this to create Share with bash script.
#!/bin/sh
STORAGE_KEY="$1"
STORAGE_ACCOUNT="$2"
SHARE_NAME="$3"
DATE_ISO=$(TZ=GMT date "+%a, %d %h %Y %H:%M:%S %Z")
VERSION="2015-12-11"
HEADER_RESOURCE="x-ms-date:$DATE_ISO\nx-ms-version:$VERSION"
URL_RESOURCE="/$STORAGE_ACCOUNT/$SHARE_NAME\nrestype:share"
STRING_TO_SIGN="PUT\n\n\n\n\n\n\n\n\n\n\n\n$HEADER_RESOURCE\n$URL_RESOURCE"
DECODED_KEY="$(echo -n $STORAGE_KEY | base64 -d -w0 | xxd -p -c256)"
SIGN=$(printf "$STRING_TO_SIGN" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$DECODED_KEY" -binary | base64 -w0)
curl -X PUT \
-H "x-ms-date:$DATE_ISO" \
-H "x-ms-version:$VERSION" \
-H "Authorization: SharedKey $STORAGE_ACCOUNT:$SIGN" \
-H "Content-Length:0" \
"https://$STORAGE_ACCOUNT.file.core.windows.net/$SHARE_NAME?restype=share"
Try this to create Directory under the specified share.
#!/bin/sh
STORAGE_KEY="$1"
STORAGE_ACCOUNT="$2"
SHARE_NAME="$3"
DIRECTORY_NAME="$4"
DATE_ISO=$(TZ=GMT date "+%a, %d %h %Y %H:%M:%S %Z")
VERSION="2015-12-11"
HEADER_RESOURCE="x-ms-date:$DATE_ISO\nx-ms-version:$VERSION"
URL_RESOURCE="/$STORAGE_ACCOUNT/$SHARE_NAME/$DIRECTORY_NAME\nrestype:directory"
STRING_TO_SIGN="PUT\n\n\n\n\n\n\n\n\n\n\n\n$HEADER_RESOURCE\n$URL_RESOURCE"
DECODED_KEY="$(echo -n $STORAGE_KEY | base64 -d -w0 | xxd -p -c256)"
SIGN=$(printf "$STRING_TO_SIGN" | openssl dgst -sha256 -mac HMAC -macopt "hexkey:$DECODED_KEY" -binary | base64 -w0)
curl -X PUT \
-H "x-ms-date:$DATE_ISO" \
-H "x-ms-version:$VERSION" \
-H "Authorization: SharedKey $STORAGE_ACCOUNT:$SIGN" \
-H "Content-Length:0" \
"https://$STORAGE_ACCOUNT.file.core.windows.net/$SHARE_NAME/$DIRECTORY_NAME?restype=directory"
I searched the other posts since I am not the only person with signature issues. I tried it with couple of languages and I always have the same problem.
What am I doing wrong with the API authentication with coinbase.com:
# normally I fetch the timestamp from https://api.coinbase.com/v2/time
TIMESTAMP=$(date +%s)
SIG=$(echo -n "${TIMESTAMP}GET/v2/accounts" | hmac256 --stdkey $COINBASE_SECRET)
curl https://api.coinbase.com/v2/accounts \
--header "CB-ACCESS-KEY: $COINBASE_KEY" \
--header "CB-ACCESS-SIGN: $SIG" \
--header "CB-ACCESS-TIMESTAMP: $TIMESTAMP" \
--header "CB-VERSION: 2016-03-08"
In go I am trying to do something like:
nonce := strconv.FormatInt(int64(time.Data.Epoch), 10)
message := nonce + req.Method + endpoint // endpoint "/v2/accounts"
req.Header.Set("CB-ACCESS-KEY", a.Key)
h := hmac.New(sha256.New, []byte(a.Secret))
h.Write([]byte(message))
signature := hex.EncodeToString(h.Sum(nil))
req.Header.Set("CB-ACCESS-SIGN", signature)
req.Header.Set("CB-ACCESS-TIMESTAMP", nonce)
req.Header.Set("CB-VERSION", "2016-03-08")
Also it seams that the sandbox is no longer supported since api.sandbox.coinbase.com is unavailable?!
Kind regards
For bash/curl the issue was the hmac tool I used with echo. Following worked for me with curl requests:
SIG=$(echo -n "${TIMESTAMP}GET/v2/accounts" | openssl dgst -sha256 -hmac "$COINBASE_SECRET" |cut -d' ' -f2);
In respect of golang I compared the hash sums and came to the conclusion that something is fishy with the current library I am using.
I wrote a library on my own (https://github.com/Zauberstuhl/go-coinbase) and now it works like a charm.
I am doing the same like above except I am using Sprintf for the final encoding but that should be the same.
Thanks anyway!