blockstack
Version:
The Blockstack Javascript library for authentication, identity, and storage.
185 lines • 6.82 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const bitcoinjs_lib_1 = require("bitcoinjs-lib");
const jsontokens_1 = require("jsontokens");
const utils_1 = require("../utils");
const fetchUtil_1 = require("../fetchUtil");
const keys_1 = require("../keys");
const logger_1 = require("../logger");
const cryptoRandom_1 = require("../encryption/cryptoRandom");
const sha2Hash_1 = require("../encryption/sha2Hash");
/**
* @ignore
*/
exports.BLOCKSTACK_GAIA_HUB_LABEL = 'blockstack-gaia-hub-config';
/**
*
* @param filename
* @param contents
* @param hubConfig
* @param contentType
*
* @ignore
*/
function uploadToGaiaHub(filename, contents, hubConfig, contentType = 'application/octet-stream', newFile = true, etag, dangerouslyIgnoreEtag) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
logger_1.Logger.debug(`uploadToGaiaHub: uploading ${filename} to ${hubConfig.server}`);
const headers = {
'Content-Type': contentType,
Authorization: `bearer ${hubConfig.token}`
};
if (!dangerouslyIgnoreEtag) {
if (newFile) {
headers['If-None-Match'] = '*';
}
else if (etag) {
headers['If-Match'] = etag;
}
}
const response = yield fetchUtil_1.fetchPrivate(`${hubConfig.server}/store/${hubConfig.address}/${filename}`, {
method: 'POST',
headers,
body: contents
});
if (!response.ok) {
throw yield utils_1.getBlockstackErrorFromResponse(response, 'Error when uploading to Gaia hub.', hubConfig);
}
const responseText = yield response.text();
const responseJSON = JSON.parse(responseText);
return responseJSON;
});
}
exports.uploadToGaiaHub = uploadToGaiaHub;
function deleteFromGaiaHub(filename, hubConfig) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
logger_1.Logger.debug(`deleteFromGaiaHub: deleting ${filename} from ${hubConfig.server}`);
const response = yield fetchUtil_1.fetchPrivate(`${hubConfig.server}/delete/${hubConfig.address}/${filename}`, {
method: 'DELETE',
headers: {
Authorization: `bearer ${hubConfig.token}`
}
});
if (!response.ok) {
throw yield utils_1.getBlockstackErrorFromResponse(response, 'Error deleting file from Gaia hub.', hubConfig);
}
});
}
exports.deleteFromGaiaHub = deleteFromGaiaHub;
/**
*
* @param filename
* @param hubConfig
*
* @ignore
*/
function getFullReadUrl(filename, hubConfig) {
return Promise.resolve(`${hubConfig.url_prefix}${hubConfig.address}/${filename}`);
}
exports.getFullReadUrl = getFullReadUrl;
/**
*
* @param challengeText
* @param signerKeyHex
*
* @ignore
*/
function makeLegacyAuthToken(challengeText, signerKeyHex) {
// only sign specific legacy auth challenges.
let parsedChallenge;
try {
parsedChallenge = JSON.parse(challengeText);
}
catch (err) {
throw new Error('Failed in parsing legacy challenge text from the gaia hub.');
}
if (parsedChallenge[0] === 'gaiahub'
&& parsedChallenge[3] === 'blockstack_storage_please_sign') {
const signer = keys_1.hexStringToECPair(signerKeyHex
+ (signerKeyHex.length === 64 ? '01' : ''));
const digest = sha2Hash_1.hashSha256Sync(Buffer.from(challengeText));
const signatureBuffer = signer.sign(digest);
const signatureWithHash = bitcoinjs_lib_1.script.signature.encode(signatureBuffer, bitcoinjs_lib_1.Transaction.SIGHASH_NONE);
// We only want the DER encoding so remove the sighash version byte at the end.
// See: https://github.com/bitcoinjs/bitcoinjs-lib/issues/1241#issuecomment-428062912
const signature = signatureWithHash.toString('hex').slice(0, -2);
const publickey = keys_1.getPublicKeyFromPrivate(signerKeyHex);
const token = Buffer.from(JSON.stringify({ publickey, signature })).toString('base64');
return token;
}
else {
throw new Error('Failed to connect to legacy gaia hub. If you operate this hub, please update.');
}
}
/**
*
* @param hubInfo
* @param signerKeyHex
* @param hubUrl
* @param associationToken
*
* @ignore
*/
function makeV1GaiaAuthToken(hubInfo, signerKeyHex, hubUrl, associationToken) {
const challengeText = hubInfo.challenge_text;
const handlesV1Auth = (hubInfo.latest_auth_version
&& parseInt(hubInfo.latest_auth_version.slice(1), 10) >= 1);
const iss = keys_1.getPublicKeyFromPrivate(signerKeyHex);
if (!handlesV1Auth) {
return makeLegacyAuthToken(challengeText, signerKeyHex);
}
const salt = cryptoRandom_1.randomBytes(16).toString('hex');
const payload = {
gaiaChallenge: challengeText,
hubUrl,
iss,
salt,
associationToken
};
const token = new jsontokens_1.TokenSigner('ES256K', signerKeyHex).sign(payload);
return `v1:${token}`;
}
/**
*
* @ignore
*/
function connectToGaiaHub(gaiaHubUrl, challengeSignerHex, associationToken) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
logger_1.Logger.debug(`connectToGaiaHub: ${gaiaHubUrl}/hub_info`);
const response = yield fetchUtil_1.fetchPrivate(`${gaiaHubUrl}/hub_info`);
const hubInfo = yield response.json();
const readURL = hubInfo.read_url_prefix;
const token = makeV1GaiaAuthToken(hubInfo, challengeSignerHex, gaiaHubUrl, associationToken);
const address = keys_1.ecPairToAddress(keys_1.hexStringToECPair(challengeSignerHex
+ (challengeSignerHex.length === 64 ? '01' : '')));
return {
url_prefix: readURL,
max_file_upload_size_megabytes: hubInfo.max_file_upload_size_megabytes,
address,
token,
server: gaiaHubUrl
};
});
}
exports.connectToGaiaHub = connectToGaiaHub;
/**
*
* @param gaiaHubUrl
* @param appPrivateKey
*
* @ignore
*/
function getBucketUrl(gaiaHubUrl, appPrivateKey) {
return tslib_1.__awaiter(this, void 0, void 0, function* () {
const challengeSigner = bitcoinjs_lib_1.ECPair.fromPrivateKey(Buffer.from(appPrivateKey, 'hex'));
const response = yield fetchUtil_1.fetchPrivate(`${gaiaHubUrl}/hub_info`);
const responseText = yield response.text();
const responseJSON = JSON.parse(responseText);
const readURL = responseJSON.read_url_prefix;
const address = keys_1.ecPairToAddress(challengeSigner);
const bucketUrl = `${readURL}${address}/`;
return bucketUrl;
});
}
exports.getBucketUrl = getBucketUrl;
//# sourceMappingURL=hub.js.map