Las entidades bancarias son responsables de almacenar y gestionar sus propios Keepers.
Los Keepers se utilizan para generar Signers y firmar Actions de forma offline.
Una vez firmado, el Action debe enviarse al núcleo de TIN Cloud utilizando el endpoint:
POST /v1/action/:action_id/sendit
- Si el Action firmado es aceptado por TIN Cloud, recibirá
labels.status: COMPLETED
y un valor en labels.hash
.
- Si es rechazado, el estado será
labels.status: REJECTED
y labels.hash
tendrá el valor none
.
Firmar Action offline
Los Keepers deben cargarse desde el sistema de gestión de llaves (KMS) antes de firmar un Action.
Para firmar un Action, necesitas su action_id
y el Keeper correspondiente a Action.source
.
💻 Código de ejemplo en Java
import java.security.MessageDigest;
import java.security.Signature;
import net.i2p.crypto.eddsa.EdDSAEngine;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.Utils;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec;
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAParameterSpec;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
public class SignatureUtil {
public static String OfflineSigning(String claimsHash, String secretKey) {
try {
// Convert private key to EdDSAPrivateKey
EdDSANamedCurveSpec ed25519 = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
EdDSAPrivateKeySpec keySpec = new EdDSAPrivateKeySpec(Utils.hexToBytes(secretKey), ed25519);
EdDSAPrivateKey privateKey = new EdDSAPrivateKey(keySpec);
// Sign the hash
EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.ED_25519);
Signature sgr = new EdDSAEngine(MessageDigest.getInstance(spec.getHashAlgorithm()));
sgr.initSign(privateKey);
sgr.update(Utils.hexToBytes(claimsHash));
byte[] signature = sgr.sign();
// Convert signature to hex string
return Utils.bytesToHex(signature);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package minka.crypto.dtos;
import java.security.KeyPair;
import net.i2p.crypto.eddsa.KeyPairGenerator;
import net.i2p.crypto.eddsa.EdDSAPublicKey;
import net.i2p.crypto.eddsa.EdDSAPrivateKey;
import net.i2p.crypto.eddsa.Utils;
public class KeeperDto {
private String publicKey;
private String secretKey;
private String scheme = "eddsa-ed25519";
public KeeperDto(String publicKey, String secretKey) {
this.publicKey = publicKey;
this.secretKey = secretKey;
}
public static KeeperDto GenerateKeys() {
KeyPairGenerator keyPairGenerator = new KeyPairGenerator();
KeyPair keyPair = keyPairGenerator.generateKeyPair();
EdDSAPublicKey publicKey = (EdDSAPublicKey) keyPair.getPublic();
EdDSAPrivateKey secretKey = (EdDSAPrivateKey) keyPair.getPrivate();
String publicKeyHexStr = Utils.bytesToHex(publicKey.getA().toByteArray());
String secretKeyHexStr = Utils.bytesToHex(secretKey.getSeed());
return new KeeperDto(publicKeyHexStr, secretKeyHexStr);
}
}
Ejemplo C##
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Signers;
using Org.BouncyCastle.Utilities.Encoders;
namespace Keeper {
public class SignatureDto
{
private List<Signatures> signatures;
public SignatureDto(HashDto hashDto, string address, string publicKey, string secretKey)
{
var decodedPrivateBytes = Hex.Decode(secretKey);
var ed25519PrivateKeyParameters = new Ed25519PrivateKeyParameters(decodedPrivateBytes, 0);
var ed25519Signer = new Ed25519Signer();
ed25519Signer.Init(true, ed25519PrivateKeyParameters);
byte[] msg = Hex.Decode(hashDto.Value);
ed25519Signer.BlockUpdate(msg, 0, msg.Length);
var signature = ed25519Signer.GenerateSignature();
var signatureHexString = Hex.ToHexString(signature);
List<Signatures> theSignatures = new List<Signatures>();
Signatures oneSignature = new Signatures();
oneSignature.Scheme = "eddsa-ed25519";
oneSignature.String = signatureHexString;
oneSignature.Signer = address;
oneSignature.Public = publicKey;
theSignatures.Add(oneSignature);
this.signatures = theSignatures;
}
public List<Signatures> Signatures
{
get => signatures;
set => signatures = value;
}
}
}
Ejemplo Node JSON
const crypto = require('crypto')
const elliptic = require('elliptic')
const eddsa25519 = new elliptic.eddsa('ed25519')
const getClaims = () => {
const date = new Date()
return {
source: 'source-address',
symbol: 'symbol-address',
target: 'target-address',
amount: '1000',
domain: 'tin',
expiry: date.toISOString(),
}
}
function signIOU(claims, privateKey) {
let eddsaKeyPair = eddsa25519.keyFromSecret(privateKey)
let signature = eddsaKeyPair.sign(claims)
return signature.toHex()
}