Strikamerki í veskispassa
Áskell getur undirritað strikamerkjagildi í veskispassa þannig að skannandi kerfi geti sannreynt að gildið hafi verið búið til af Áskeli og hafi ekki verið breytt.
Snið
Undirritað strikamerkjagildi er sent á þessu sniði:
<value>:<signature>
Reglur
valueer upprunalega strikamerkjagildið.signatureerHMAC-SHA256afvalue.Bæði
valueog leynilykillinn eru meðhöndluð semUTF-8bæti.signatureer send sem lágstafa hex strengur.Tvípunktur
:er frátekinn sem aðgreinir, þannig aðbarcode_message_templatemá ekki innihalda:.
Leynilykill
Hver wallet pass sniðmát fær sjálfkrafa búinn til deilanlegan leynilykil:
lykillinn er myndaður sjálfkrafa þegar sniðmátið er stofnað
lykillinn er ekki breytanlegur eftir á
lykilinn má sjá á sniðmátsupplýsingasíðu í stjórnborði og afrita þaðan
Virk dæmispör
Þetta dæmi má nota til að sannreyna innleiðingu:
secret = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
value = sub_SUB123
signature = fa7e0e69738cb28e457aad7e38a2aad2c66c7976b96f22d72f5d387ee6824105
barcode = sub_SUB123:fa7e0e69738cb28e457aad7e38a2aad2c66c7976b96f22d72f5d387ee6824105
Python
import hashlib
import hmac
def sign_wallet_barcode(value: str, secret: str) -> str:
signature = hmac.new(
secret.encode("utf-8"),
value.encode("utf-8"),
hashlib.sha256,
).hexdigest()
return f"{value}:{signature}"
def verify_wallet_barcode(barcode: str, secret: str) -> bool:
value, signature = barcode.rsplit(":", 1)
expected = hmac.new(
secret.encode("utf-8"),
value.encode("utf-8"),
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(signature, expected)
secret = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
barcode = "sub_SUB123:fa7e0e69738cb28e457aad7e38a2aad2c66c7976b96f22d72f5d387ee6824105"
assert sign_wallet_barcode("sub_SUB123", secret) == barcode
assert verify_wallet_barcode(barcode, secret) is True
JavaScript / Node.js
const crypto = require('crypto');
function signWalletBarcode(value, secret) {
const signature = crypto
.createHmac('sha256', Buffer.from(secret, 'utf8'))
.update(Buffer.from(value, 'utf8'))
.digest('hex');
return `${value}:${signature}`;
}
function verifyWalletBarcode(barcode, secret) {
const index = barcode.lastIndexOf(':');
const value = barcode.slice(0, index);
const signature = barcode.slice(index + 1);
const expected = crypto
.createHmac('sha256', Buffer.from(secret, 'utf8'))
.update(Buffer.from(value, 'utf8'))
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'utf8'),
Buffer.from(expected, 'utf8'),
);
}
const secret =
'0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
const barcode =
'sub_SUB123:fa7e0e69738cb28e457aad7e38a2aad2c66c7976b96f22d72f5d387ee6824105';
console.assert(signWalletBarcode('sub_SUB123', secret) === barcode);
console.assert(verifyWalletBarcode(barcode, secret) === true);
PHP
<?php
function sign_wallet_barcode(string $value, string $secret): string {
$signature = hash_hmac('sha256', $value, $secret);
return $value . ':' . $signature;
}
function verify_wallet_barcode(string $barcode, string $secret): bool {
[$value, $signature] = explode(':', $barcode, 2);
$expected = hash_hmac('sha256', $value, $secret);
return hash_equals($expected, $signature);
}
$secret = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
$barcode = 'sub_SUB123:fa7e0e69738cb28e457aad7e38a2aad2c66c7976b96f22d72f5d387ee6824105';
assert(sign_wallet_barcode('sub_SUB123', $secret) === $barcode);
assert(verify_wallet_barcode($barcode, $secret) === true);
Go
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strings"
)
func signWalletBarcode(value, secret string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(value))
signature := hex.EncodeToString(mac.Sum(nil))
return value + ":" + signature
}
func verifyWalletBarcode(barcode, secret string) bool {
index := strings.LastIndex(barcode, ":")
value := barcode[:index]
signature := barcode[index+1:]
expected := signWalletBarcode(value, secret)
expectedSignature := expected[strings.LastIndex(expected, ":")+1:]
return hmac.Equal([]byte(signature), []byte(expectedSignature))
}
func main() {
secret := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
barcode := "sub_SUB123:fa7e0e69738cb28e457aad7e38a2aad2c66c7976b96f22d72f5d387ee6824105"
fmt.Println(signWalletBarcode("sub_SUB123", secret) == barcode)
fmt.Println(verifyWalletBarcode(barcode, secret))
}
C#
using System;
using System.Security.Cryptography;
using System.Text;
static string SignWalletBarcode(string value, string secret)
{
using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));
var signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(value));
var signature = Convert.ToHexString(signatureBytes).ToLowerInvariant();
return $"{value}:{signature}";
}
static bool VerifyWalletBarcode(string barcode, string secret)
{
var index = barcode.LastIndexOf(':');
var value = barcode[..index];
var signature = barcode[(index + 1)..];
var expected = SignWalletBarcode(value, secret);
var expectedSignature = expected[(expected.LastIndexOf(':') + 1)..];
return CryptographicOperations.FixedTimeEquals(
Encoding.UTF8.GetBytes(signature),
Encoding.UTF8.GetBytes(expectedSignature)
);
}
var secret = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
var barcode = "sub_SUB123:fa7e0e69738cb28e457aad7e38a2aad2c66c7976b96f22d72f5d387ee6824105";
Console.WriteLine(SignWalletBarcode("sub_SUB123", secret) == barcode);
Console.WriteLine(VerifyWalletBarcode(barcode, secret));
Athugasemdir
Ef þið viljið sýna manneskjulesan texta undir strikamerkinu skal nota
barcode_alt_text_template. Undirritunin bætist við skannvæna gildið, ekki endilega sýnilega textann.Við sannvottun ætti alltaf að nota föst tímamælinga-samanburðaraðferð þar sem tungumálið býður upp á það, til dæmis
compare_digest,timingSafeEqualeðahash_equals.