@doctormckay/steam-crypto
Advanced tools
Comparing version 1.0.0 to 1.1.0
76
index.js
@@ -5,2 +5,8 @@ var Crypto = require('crypto'); | ||
/** | ||
* Verifies a signature using the Steam "System" public key. | ||
* @param {Buffer} data | ||
* @param {Buffer} signature | ||
* @param {string} algorithm | ||
*/ | ||
exports.verifySignature = function(data, signature, algorithm) { | ||
@@ -13,5 +19,10 @@ var verify = Crypto.createVerify(algorithm || "RSA-SHA1"); | ||
exports.generateSessionKey = function() { | ||
/** | ||
* Generate a 32-byte symmetric session key and encrypt it with Steam's public "System" key. | ||
* @param {Buffer} [nonce] - If provided, will be appended to the session key when encrypting | ||
* @returns {{plain: Buffer, encrypted: Buffer}} | ||
*/ | ||
exports.generateSessionKey = function(nonce) { | ||
var sessionKey = Crypto.randomBytes(32); | ||
var cryptedSessionKey = Crypto.publicEncrypt(g_PubkeySystem, sessionKey); | ||
var cryptedSessionKey = Crypto.publicEncrypt(g_PubkeySystem, Buffer.concat([sessionKey, nonce || new Buffer(0)])); | ||
return { | ||
@@ -23,23 +34,66 @@ plain: sessionKey, | ||
exports.symmetricEncrypt = function(input, key) { | ||
var iv = Crypto.randomBytes(16); | ||
/** | ||
* AES-encrypt some data with a symmetric key. | ||
* @param {Buffer} input | ||
* @param {Buffer} key | ||
* @param {Buffer} [iv] - If not provided, one will be generated randomly | ||
* @returns {Buffer} | ||
*/ | ||
exports.symmetricEncrypt = function(input, key, iv) { | ||
iv = iv || Crypto.randomBytes(16); | ||
var aesIv = Crypto.createCipheriv('aes-256-ecb', key, ''); | ||
aesIv.setAutoPadding(false); | ||
aesIv.end(iv); | ||
var aesData = Crypto.createCipheriv('aes-256-cbc', key, iv); | ||
aesData.end(input); | ||
return Buffer.concat([aesIv.read(), aesData.read()]); | ||
}; | ||
exports.symmetricDecrypt = function(input, key) { | ||
/** | ||
* AES-encrypt some data with a symmetric key, and add an HMAC. | ||
* @param {Buffer} input | ||
* @param {Buffer} key | ||
*/ | ||
exports.symmetricEncryptWithHmacIv = function(input, key) { | ||
// IV is HMAC-SHA1(Random(3) + Plaintext) + Random(3). (Same random values for both) | ||
var random = Crypto.randomBytes(3); | ||
var hmac = Crypto.createHmac("sha1", key.slice(0, 16)); // we only want the first 16 bytes of the key for the hmac | ||
hmac.update(random); | ||
hmac.update(input); | ||
return exports.symmetricEncrypt(input, key, Buffer.concat([hmac.digest().slice(0, 16 - random.length), random])); // the resulting IV must be 16 bytes long, so truncate the hmac to make room for the random | ||
}; | ||
/** | ||
* AES-decrypt some data with a symmetric key, and optionally check an HMAC. | ||
* @param {Buffer} input | ||
* @param {Buffer} key | ||
* @param {boolean} [checkHmac=false] - Does this data contain an HMAC for us to check? | ||
* @returns {*} | ||
*/ | ||
exports.symmetricDecrypt = function(input, key, checkHmac) { | ||
var aesIv = Crypto.createDecipheriv('aes-256-ecb', key, ''); | ||
aesIv.setAutoPadding(false); | ||
aesIv.end(input.slice(0, 16)); | ||
var aesData = Crypto.createDecipheriv('aes-256-cbc', key, aesIv.read()); | ||
var iv = aesIv.read(); | ||
var aesData = Crypto.createDecipheriv('aes-256-cbc', key, iv); | ||
aesData.end(input.slice(16)); | ||
return aesData.read(); | ||
var plaintext = aesData.read(); | ||
if (checkHmac) { | ||
// The last 3 bytes of the IV are a random value, and the remainder are a partial HMAC | ||
var remotePartialHmac = iv.slice(0, iv.length - 3); | ||
var random = iv.slice(iv.length - 3, iv.length); | ||
var hmac = Crypto.createHmac("sha1", key.slice(0, 16)); | ||
hmac.update(random); | ||
hmac.update(plaintext); | ||
if (!remotePartialHmac.equals(hmac.digest().slice(0, remotePartialHmac.length))) { | ||
throw new Error("Received invalid HMAC from remote host."); | ||
} | ||
} | ||
return plaintext; | ||
}; |
{ | ||
"name": "@doctormckay/steam-crypto", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Node.js implementation of Valve's crypto", | ||
@@ -5,0 +5,0 @@ "repository": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
19958
14
84