You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
	
	
		
			113 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
		
		
			
		
	
	
			113 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			TypeScript
		
	
| 
											7 years ago
										 | import { createHash } from 'crypto'; | ||
|  | import { | ||
|  |   createReadStream, | ||
|  |   readFile as readFileCallback, | ||
|  |   writeFile as writeFileCallback, | ||
|  | } from 'fs'; | ||
|  | import { basename, dirname, join, resolve as resolvePath } from 'path'; | ||
|  | 
 | ||
|  | import pify from 'pify'; | ||
|  | 
 | ||
|  | import { BinaryType, sign, verify } from './curve'; | ||
|  | 
 | ||
|  | const readFile = pify(readFileCallback); | ||
|  | const writeFile = pify(writeFileCallback); | ||
|  | 
 | ||
|  | export async function generateSignature( | ||
|  |   updatePackagePath: string, | ||
|  |   version: string, | ||
|  |   privateKeyPath: string | ||
|  | ) { | ||
|  |   const privateKey = await loadHexFromPath(privateKeyPath); | ||
|  |   const message = await generateMessage(updatePackagePath, version); | ||
|  | 
 | ||
|  |   return sign(privateKey, message); | ||
|  | } | ||
|  | 
 | ||
|  | export async function verifySignature( | ||
|  |   updatePackagePath: string, | ||
|  |   version: string, | ||
|  |   publicKey: BinaryType | ||
|  | ): Promise<boolean> { | ||
|  |   const signaturePath = getSignaturePath(updatePackagePath); | ||
|  |   const signature = await loadHexFromPath(signaturePath); | ||
|  |   const message = await generateMessage(updatePackagePath, version); | ||
|  | 
 | ||
|  |   return verify(publicKey, message, signature); | ||
|  | } | ||
|  | 
 | ||
|  | // Helper methods
 | ||
|  | 
 | ||
|  | async function generateMessage( | ||
|  |   updatePackagePath: string, | ||
|  |   version: string | ||
|  | ): Promise<BinaryType> { | ||
|  |   const hash = await _getFileHash(updatePackagePath); | ||
|  |   const messageString = `${Buffer.from(hash).toString('hex')}-${version}`; | ||
|  | 
 | ||
|  |   return Buffer.from(messageString); | ||
|  | } | ||
|  | 
 | ||
|  | export async function writeSignature( | ||
|  |   updatePackagePath: string, | ||
|  |   version: string, | ||
|  |   privateKeyPath: string | ||
|  | ) { | ||
|  |   const signaturePath = getSignaturePath(updatePackagePath); | ||
|  |   const signature = await generateSignature( | ||
|  |     updatePackagePath, | ||
|  |     version, | ||
|  |     privateKeyPath | ||
|  |   ); | ||
|  |   await writeHexToPath(signaturePath, signature); | ||
|  | } | ||
|  | 
 | ||
|  | export async function _getFileHash( | ||
|  |   updatePackagePath: string | ||
|  | ): Promise<BinaryType> { | ||
|  |   const hash = createHash('sha256'); | ||
|  |   const stream = createReadStream(updatePackagePath); | ||
|  | 
 | ||
|  |   return new Promise((resolve, reject) => { | ||
|  |     stream.on('data', data => { | ||
|  |       hash.update(data); | ||
|  |     }); | ||
|  |     stream.on('close', () => { | ||
|  |       resolve(hash.digest()); | ||
|  |     }); | ||
|  |     stream.on('error', error => { | ||
|  |       reject(error); | ||
|  |     }); | ||
|  |   }); | ||
|  | } | ||
|  | 
 | ||
|  | export function getSignatureFileName(fileName: string) { | ||
|  |   return `${fileName}.sig`; | ||
|  | } | ||
|  | 
 | ||
|  | export function getSignaturePath(updatePackagePath: string): string { | ||
|  |   const updateFullPath = resolvePath(updatePackagePath); | ||
|  |   const updateDir = dirname(updateFullPath); | ||
|  |   const updateFileName = basename(updateFullPath); | ||
|  | 
 | ||
|  |   return join(updateDir, getSignatureFileName(updateFileName)); | ||
|  | } | ||
|  | 
 | ||
|  | export function hexToBinary(target: string): BinaryType { | ||
|  |   return Buffer.from(target, 'hex'); | ||
|  | } | ||
|  | 
 | ||
|  | export function binaryToHex(data: BinaryType): string { | ||
|  |   return Buffer.from(data).toString('hex'); | ||
|  | } | ||
|  | 
 | ||
|  | export async function loadHexFromPath(target: string): Promise<BinaryType> { | ||
|  |   const hexString = await readFile(target, 'utf8'); | ||
|  | 
 | ||
|  |   return hexToBinary(hexString); | ||
|  | } | ||
|  | 
 | ||
|  | export async function writeHexToPath(target: string, data: BinaryType) { | ||
|  |   await writeFile(target, binaryToHex(data)); | ||
|  | } |