import { Buffer } from '@stacks/common' ; import 'cross-fetch/polyfill' ; import { TokenSigner , SECP256K1Client } from 'jsontokens' ; import { makeUUID4 , nextMonth , getGlobalObject } from '@stacks/common' ; import { makeDIDFromAddress } from './dids' ; import { encryptECIES , decryptECIES , makeECPrivateKey , publicKeyToAddress , } from '@stacks/encryption' ; import { DEFAULT_SCOPE , AuthScope } from './constants' ; const VERSION = '1.3.1' ; type AuthMetadata = { email ? : string ; profileUrl ? : string ; } ; param { SessionData } session return { String } private ignore export function generateTransitKey ( ) { const transitKey = makeECPrivateKey ( ) ; return transitKey ; } param { String } transitPrivateKey param { String } redirectURI param { String } manifestURI param { ( AuthScope | string ) [ ] } scopes param { String } appDomain param { Number } expiresAt param { Object } extraParams return { String } export function makeAuthRequest ( transitPrivateKey , redirectURI ? , manifestURI ? , scopes = DEFAULT_SCOPE . slice ( ) , appDomain ? , expiresAt = nextMonth ( ) . getTime ( ) , extraParams = { } ) { const getWindowOrigin = ( paramName ) => { const location = getGlobalObject ( 'location' , { throwIfUnavailable : true , usageDesc : `makeAuthRequest([${ paramName }=undefined])` , } ) ; return location ?. origin ; } ; if ( ! redirectURI ) { redirectURI = `${ getWindowOrigin ( 'redirectURI' ) }/` ; } if ( ! manifestURI ) { manifestURI = `${ getWindowOrigin ( 'manifestURI' ) }/manifest.json` ; } if ( ! appDomain ) { appDomain = getWindowOrigin ( 'appDomain' ) ; } const payload = Object . assign ( { } , extraParams , { jti : makeUUID4 ( ) , iat : Math . floor ( new Date ( ) . getTime ( ) / 1000 ) , exp : Math . floor ( expiresAt / 1000 ) , iss : null , public_keys : [ ] , domain_name : appDomain , manifest_uri : manifestURI , redirect_uri : redirectURI , version : VERSION , do_not_include_profile : true , supports_hub_url : true , scopes , } ) ; const publicKey = SECP256K1Client . derivePublicKey ( transitPrivateKey ) ; payload . public_keys = [ publicKey ] ; const address = publicKeyToAddress ( publicKey ) ; payload . iss = makeDIDFromAddress ( address ) ; const tokenSigner = new TokenSigner ( 'ES256k' , transitPrivateKey ) ; const token = tokenSigner . sign ( payload ) ; return token ; } param { String } publicKey param { String } privateKey return { String } private ignore export async function encryptPrivateKey ( publicKey , privateKey ) { const encryptedObj = await encryptECIES ( publicKey , Buffer . from ( privateKey ) , true ) ; const encryptedJSON = JSON . stringify ( encryptedObj ) ; return Buffer . from ( encryptedJSON ) . toString ( 'hex' ) ; } param { String } privateKey param { String } hexedEncrypted return { String } throws private ignore export async function decryptPrivateKey ( privateKey , hexedEncrypted ) { const unhexedString = Buffer . from ( hexedEncrypted , 'hex' ) . toString ( ) ; const encryptedObj = JSON . parse ( unhexedString ) ; const decrypted = await decryptECIES ( privateKey , encryptedObj ) ; if ( typeof decrypted !== 'string' ) { throw new Error ( 'Unable to correctly decrypt private key' ) ; } else { return decrypted ; } } param { String } privateKey param { Object } profile param { String } username param { AuthMetadata } metadata param { String } coreToken param { String } appPrivateKey param { Number } expiresAt param { String } transitPublicKey param { String } hubUrl param { String } blockstackAPIUrl param { String } associationToken return { String } private ignore export async function makeAuthResponse ( privateKey , profile = { } , username = null , metadata , coreToken = null , appPrivateKey = null , expiresAt = nextMonth ( ) . getTime ( ) , transitPublicKey = null , hubUrl = null , blockstackAPIUrl = null , associationToken = null ) { const publicKey = SECP256K1Client . derivePublicKey ( privateKey ) ; const address = publicKeyToAddress ( publicKey ) ; let privateKeyPayload = appPrivateKey ; let coreTokenPayload = coreToken ; let additionalProperties = { } ; if ( appPrivateKey !== undefined && appPrivateKey !== null ) { if ( transitPublicKey !== undefined && transitPublicKey !== null ) { privateKeyPayload = await encryptPrivateKey ( transitPublicKey , appPrivateKey ) ; if ( coreToken !== undefined && coreToken !== null ) { coreTokenPayload = await encryptPrivateKey ( transitPublicKey , coreToken ) ; } } additionalProperties = { email : metadata ?. email ? metadata . email : null , profile_url : metadata ?. profileUrl ? metadata . profileUrl : null , hubUrl , blockstackAPIUrl , associationToken , version : VERSION , } ; } else { } const payload = Object . assign ( { } , { jti : makeUUID4 ( ) , iat : Math . floor ( new Date ( ) . getTime ( ) / 1000 ) , exp : Math . floor ( expiresAt / 1000 ) , iss : makeDIDFromAddress ( address ) , private_key : privateKeyPayload , public_keys : [ publicKey ] , profile , username , core_token : coreTokenPayload , } , additionalProperties ) ; const tokenSigner = new TokenSigner ( 'ES256k' , privateKey ) ; return tokenSigner . sign ( payload ) ; }