SHA256
GPT: сгенерено и не проверено (смена ключей пользователя)
This commit is contained in:
@@ -123,3 +123,81 @@ export async function createAns104DataItem({ owner32, privateKey, data, tags = [
|
||||
data,
|
||||
);
|
||||
}
|
||||
|
||||
function readUint64LE(bytes, offset) {
|
||||
if (!(bytes instanceof Uint8Array) || offset < 0 || offset + 8 > bytes.length) throw new Error('ANS-104 truncated uint64');
|
||||
let value = 0n;
|
||||
for (let i = 7; i >= 0; i -= 1) value = (value << 8n) | BigInt(bytes[offset + i]);
|
||||
if (value > BigInt(Number.MAX_SAFE_INTEGER)) throw new Error('ANS-104 uint64 exceeds JS safe integer');
|
||||
return Number(value);
|
||||
}
|
||||
|
||||
/** Parse enough of an Ed25519 ANS-104 DataItem to re-sign its exact SHiNE payload. */
|
||||
export function parseAns104DataItem(rawBytes) {
|
||||
const raw = rawBytes instanceof Uint8Array ? rawBytes : Uint8Array.from(rawBytes || []);
|
||||
let p = 0;
|
||||
if (raw.length < 2 + 64 + 32 + 1 + 1 + 8 + 8) throw new Error('ANS-104 DataItem is too short');
|
||||
const sigType = new DataView(raw.buffer, raw.byteOffset, raw.byteLength).getUint16(p, true); p += 2;
|
||||
if (sigType !== ANS104_ED25519_SIGNATURE_TYPE) throw new Error(`Unsupported ANS-104 signature type: ${sigType}`);
|
||||
const signature = raw.slice(p, p + 64); p += 64;
|
||||
const owner32 = raw.slice(p, p + 32); p += 32;
|
||||
const targetPresent = raw[p++] !== 0;
|
||||
const target = targetPresent ? raw.slice(p, p + 32) : new Uint8Array(0);
|
||||
if (targetPresent) p += 32;
|
||||
const anchorPresent = raw[p++] !== 0;
|
||||
const anchor = anchorPresent ? raw.slice(p, p + 32) : new Uint8Array(0);
|
||||
if (anchorPresent) p += 32;
|
||||
const tagsCount = readUint64LE(raw, p); p += 8;
|
||||
const tagsBytesLength = readUint64LE(raw, p); p += 8;
|
||||
if (p + tagsBytesLength > raw.length) throw new Error('ANS-104 tags are truncated');
|
||||
const rawTags = raw.slice(p, p + tagsBytesLength); p += tagsBytesLength;
|
||||
const data = raw.slice(p);
|
||||
return { sigType, signature, owner32, target, anchor, tagsCount, rawTags, data, raw };
|
||||
}
|
||||
|
||||
async function ans104SigningMessageRaw({ owner32, target = new Uint8Array(0), anchor = new Uint8Array(0), rawTags, data }) {
|
||||
if (!(owner32 instanceof Uint8Array) || owner32.length !== 32) throw new Error('ANS-104 owner must be 32 bytes');
|
||||
if (!(target instanceof Uint8Array) || (target.length !== 0 && target.length !== 32)) throw new Error('ANS-104 target must be empty or 32 bytes');
|
||||
if (!(anchor instanceof Uint8Array) || (anchor.length !== 0 && anchor.length !== 32)) throw new Error('ANS-104 anchor must be empty or 32 bytes');
|
||||
if (!(rawTags instanceof Uint8Array)) throw new Error('ANS-104 rawTags must be Uint8Array');
|
||||
if (!(data instanceof Uint8Array)) throw new Error('ANS-104 data must be Uint8Array');
|
||||
return deepHash([
|
||||
TE.encode('dataitem'),
|
||||
TE.encode('1'),
|
||||
TE.encode(String(ANS104_ED25519_SIGNATURE_TYPE)),
|
||||
owner32,
|
||||
target,
|
||||
anchor,
|
||||
rawTags,
|
||||
data,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-sign a DataItem while preserving exact raw tags/target/anchor/data bytes.
|
||||
* Used by key rotation so SHA-256(SHiNE Frame) is unchanged across forks.
|
||||
*/
|
||||
export async function createAns104DataItemWithRawParts({
|
||||
owner32,
|
||||
privateKey,
|
||||
data,
|
||||
rawTags,
|
||||
tagsCount,
|
||||
target = new Uint8Array(0),
|
||||
anchor = new Uint8Array(0),
|
||||
}) {
|
||||
const signingMessage = await ans104SigningMessageRaw({ owner32, target, anchor, rawTags, data });
|
||||
const signature = new Uint8Array(await crypto.subtle.sign('Ed25519', privateKey, signingMessage));
|
||||
if (signature.length !== 64) throw new Error(`Unexpected Ed25519 signature length: ${signature.length}`);
|
||||
return concatBytes(
|
||||
uint16LE(ANS104_ED25519_SIGNATURE_TYPE),
|
||||
signature,
|
||||
owner32,
|
||||
Uint8Array.of(target.length ? 1 : 0), target,
|
||||
Uint8Array.of(anchor.length ? 1 : 0), anchor,
|
||||
uint64LE(tagsCount),
|
||||
uint64LE(rawTags.length),
|
||||
rawTags,
|
||||
data,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user