Created
June 20, 2023 18:56
-
-
Save Ne3tCode/fc43e0211c04c5f1b8a345272bd89b8c to your computer and use it in GitHub Desktop.
[UserScript] Steam Mobile Confirmations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Steam Community Mobile Trade Confirmations | |
// @namespace www.doctormckay.com | |
// @description Enables mobile trade confirmations in the web browser | |
// @match https://steamcommunity.com/mobileconf/conf* | |
// @version 1.2.0 | |
// @author DoctorMcKay, Nephrite | |
// @grant none | |
// @run-at document-end | |
// ==/UserScript== | |
/* eslint-disable no-redeclare */ | |
/* | |
CryptoJS v3.1.2 | |
code.google.com/p/crypto-js | |
(c) 2009-2013 by Jeff Mott. All rights reserved. | |
code.google.com/p/crypto-js/wiki/License | |
*/ | |
// http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/hmac-sha1.js | |
// core | |
var CryptoJS=CryptoJS||function(g,l){var e={},d=e.lib={},m=function(){},k=d.Base={extend:function(a){m.prototype=this;var c=new m;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, | |
p=d.WordArray=k.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=l?c:4*a.length},toString:function(a){return(a||n).stringify(this)},concat:function(a){var c=this.words,q=a.words,f=this.sigBytes;a=a.sigBytes;this.clamp();if(f%4)for(var b=0;b<a;b++)c[f+b>>>2]|=(q[b>>>2]>>>24-8*(b%4)&255)<<24-8*((f+b)%4);else if(65535<q.length)for(b=0;b<a;b+=4)c[f+b>>>2]=q[b>>>2];else c.push.apply(c,q);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< | |
32-8*(c%4);a.length=g.ceil(c/4)},clone:function(){var a=k.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],b=0;b<a;b+=4)c.push(4294967296*g.random()|0);return new p.init(c,a)}}),b=e.enc={},n=b.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],f=0;f<a;f++){var d=c[f>>>2]>>>24-8*(f%4)&255;b.push((d>>>4).toString(16));b.push((d&15).toString(16))}return b.join("")},parse:function(a){for(var c=a.length,b=[],f=0;f<c;f+=2){b[f>>>3]|=parseInt(a.substr(f, | |
2),16)<<24-4*(f%8)};return new p.init(b,c/2)}},j=b.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var b=[],f=0;f<a;f++)b.push(String.fromCharCode(c[f>>>2]>>>24-8*(f%4)&255));return b.join("")},parse:function(a){for(var c=a.length,b=[],f=0;f<c;f++)b[f>>>2]|=(a.charCodeAt(f)&255)<<24-8*(f%4);return new p.init(b,c)}},h=b.Utf8={stringify:function(a){try{return decodeURIComponent(escape(j.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return j.parse(unescape(encodeURIComponent(a)))}}, | |
r=d.BufferedBlockAlgorithm=k.extend({reset:function(){this._data=new p.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=h.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,b=c.words,f=c.sigBytes,d=this.blockSize,e=f/(4*d),e=a?g.ceil(e):g.max((e|0)-this._minBufferSize,0);a=e*d;f=g.min(4*a,f);if(a){for(var k=0;k<a;k+=d)this._doProcessBlock(b,k);k=b.splice(0,a);c.sigBytes-=f}return new p.init(k,f)},clone:function(){var a=k.clone.call(this); | |
a._data=this._data.clone();return a},_minBufferSize:0});d.Hasher=r.extend({cfg:k.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){r.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,d){return(new a.init(d)).finalize(b)}},_createHmacHelper:function(a){return function(b,d){return(new s.HMAC.init(a, | |
d)).finalize(b)}}});var s=e.algo={};return e}(Math); | |
// sha1 | |
(function(){var g=CryptoJS,l=g.lib,e=l.WordArray,d=l.Hasher,m=[],l=g.algo.SHA1=d.extend({_doReset:function(){this._hash=new e.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(d,e){for(var b=this._hash.words,n=b[0],j=b[1],h=b[2],g=b[3],l=b[4],a=0;80>a;a++){if(16>a)m[a]=d[e+a]|0;else{var c=m[a-3]^m[a-8]^m[a-14]^m[a-16];m[a]=c<<1|c>>>31}c=(n<<5|n>>>27)+l+m[a];c=20>a?c+((j&h|~j&g)+1518500249):40>a?c+((j^h^g)+1859775393):60>a?c+((j&h|j&g|h&g)-1894007588):c+((j^h^ | |
g)-899497514);l=g;g=h;h=j<<30|j>>>2;j=n;n=c}b[0]=b[0]+n|0;b[1]=b[1]+j|0;b[2]=b[2]+h|0;b[3]=b[3]+g|0;b[4]=b[4]+l|0},_doFinalize:function(){var d=this._data,e=d.words,b=8*this._nDataBytes,g=8*d.sigBytes;e[g>>>5]|=128<<24-g%32;e[(g+64>>>9<<4)+14]=Math.floor(b/4294967296);e[(g+64>>>9<<4)+15]=b;d.sigBytes=4*e.length;this._process();return this._hash},clone:function(){var e=d.clone.call(this);e._hash=this._hash.clone();return e}});g.SHA1=d._createHelper(l);g.HmacSHA1=d._createHmacHelper(l)})(); | |
// hmac | |
(function(){var g=CryptoJS,l=g.enc.Utf8;g.algo.HMAC=g.lib.Base.extend({init:function(e,d){e=this._hasher=new e.init;"string"==typeof d&&(d=l.parse(d));var g=e.blockSize,k=4*g;d.sigBytes>k&&(d=e.finalize(d));d.clamp();for(var p=this._oKey=d.clone(),b=this._iKey=d.clone(),n=p.words,j=b.words,h=0;h<g;h++){n[h]^=1549556828;j[h]^=909522486};p.sigBytes=b.sigBytes=k;this.reset()},reset:function(){var e=this._hasher;e.reset();e.update(this._iKey)},update:function(e){this._hasher.update(e);return this},finalize:function(e){var d= | |
this._hasher;e=d.finalize(e);d.reset();return d.finalize(this._oKey.clone().concat(e))}})})(); | |
// http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/enc-base64-min.js | |
// base64 | |
(function(){var h=CryptoJS,j=h.lib.WordArray;h.enc.Base64={stringify:function(b){var e=b.words,f=b.sigBytes,c=this._map;b.clamp();b=[];for(var a=0;a<f;a+=3)for(var d=(e[a>>>2]>>>24-8*(a%4)&255)<<16|(e[a+1>>>2]>>>24-8*((a+1)%4)&255)<<8|e[a+2>>>2]>>>24-8*((a+2)%4)&255,g=0;4>g&&a+0.75*g<f;g++)b.push(c.charAt(d>>>6*(3-g)&63));if(e=c.charAt(64))for(;b.length%4;)b.push(e);return b.join("")},parse:function(b){var e=b.length,f=this._map,c=f.charAt(64);c&&(c=b.indexOf(c),-1!=c&&(e=c));for(var c=[],a=0,d=0;d< | |
e;d++)if(d%4){var g=f.indexOf(b.charAt(d-1))<<2*(d%4),h=f.indexOf(b.charAt(d))>>>6-2*(d%4);c[a>>>2]|=(g|h)<<24-8*(a%4);a++}return j.create(c,a)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); | |
/* | |
End of CryptoJS | |
*/ | |
/* eslint-enable no-redeclare */ | |
var storage = { | |
setValue: function(key, value) { | |
localStorage.setItem(key, value); | |
}, | |
getValue: function(key, def) { | |
return localStorage.getItem(key) || def; | |
}, | |
deleteValue: function(key) { | |
localStorage.removeItem(key); | |
} | |
}; | |
var g_DefaultDeviceID = "android:" + CryptoJS.SHA1(window.g_steamID).toString().replace(/^([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12}).*$/, '$1-$2-$3-$4-$5'); | |
var g_DeviceID = null; | |
function error(msg) { | |
storage.setValue("errormsg", msg); | |
window.location.href = "/mobileconf/conf?options"; | |
} | |
if (window.location.href.match(/mobileconf/)) { | |
window.SGHandler = {"getResultStatus": function() { return "busy"; }, "getResultValue": function() { return ""; }}; | |
window.GetValueFromLocalURL = function(url, timeout, success, error, fatal) { | |
console.log('url: ' + url); | |
var tag = url.match(/op=conftag&arg1=(\w+)/)[1]; | |
getKey(tag, function(time, key) { | |
success("p=" + encodeURIComponent(g_DeviceID || g_DefaultDeviceID) + "&a=" + window.g_steamID + "&k=" + encodeURIComponent(key) + "&t=" + time + "&m=android&tag=" + tag); | |
}); | |
}; | |
getAccountName(function(accountName) { | |
if (!accountName) { | |
error("Couldn't get your account name."); | |
return; | |
} | |
g_DeviceID = storage.getValue(accountName + ":device_id", "").trim(); | |
if (!window.location.search || window.location.search == "?options") { | |
var identitySecret = storage.getValue(accountName + ":identity_secret", "").trim(); | |
if (window.location.search == "?options" || !identitySecret) { | |
var errormsg = storage.getValue("errormsg"); | |
var $error = window.$J('<p style="color: #c00"></p>'); | |
if (errormsg) { | |
$error.text(errormsg); | |
storage.deleteValue("errormsg"); | |
} | |
var $identitySecret = window.$J('<p>Enter your identity secret: <input type="text" size="100" placeholder="blahblahblahblah=" style="padding: 3px; border-color: #222; color: #ccc" value="' + identitySecret + '" /></p>'); | |
var $deviceID = window.$J('<p>Enter your DeviceID: <input type="text" size="100" placeholder="' + g_DefaultDeviceID + ' (autogenerated)" style="padding: 3px; border-color: #222; color: #ccc" value="' + g_DeviceID + '" /></p>'); | |
var $save = window.$J('<p><button type="button" id="gm_save">Save</button></p>'); | |
var $empty = window.$J('#mobileconf_empty'); | |
$empty.html($error).append($identitySecret).append($deviceID).append($save); | |
$save.find('button').click(function() { | |
storage.setValue(accountName + ":identity_secret", $identitySecret.find('input').val().trim()); | |
g_DeviceID = $deviceID.find('input').val().trim(); | |
storage.setValue(accountName + ":device_id", g_DeviceID); | |
redirectToConf(); | |
}); | |
} else { | |
redirectToConf(); | |
} | |
} else { | |
if (!g_DeviceID) { | |
g_DeviceID = g_DefaultDeviceID; | |
} | |
window.$J('#mobileconf_empty').append('<div style="margin-top: 20px"><a href="/mobileconf/conf?options" style="text-decoration: underline">Change identity secret</a></div>'); | |
} | |
}); | |
window.$J('#mobileconf_done').append('<div style="margin-top: 20px"><a href="/mobileconf/conf" style="text-decoration: underline">Back / Reload</a></div>'); | |
} | |
function redirectToConf(suppressDialog) { | |
if (!suppressDialog) { | |
window.ShowBlockingWaitDialog('Loading...', 'Loading your confirmations...'); | |
} | |
getKey("conf", function(time, key) { | |
window.location.href = "/mobileconf/conf?p=" + encodeURIComponent(g_DeviceID || g_DefaultDeviceID) + "&a=" + window.g_steamID + "&k=" + encodeURIComponent(key) + "&t=" + time + "&m=android&tag=conf"; | |
}); | |
} | |
function getAccountName(callback) { | |
var accountName = window.$J('#account_dropdown .persona').text().trim(); | |
if (accountName) { | |
callback(accountName); | |
return; | |
} | |
// It's not on this page | |
window.$J.get('/', function(html) { | |
accountName = html.match(/<span [^>]*class="persona online"[^>]*>([^<]+)<\/span>/); | |
if (!accountName) { | |
callback(null); | |
} else { | |
callback(accountName[1].trim()); | |
} | |
}); | |
} | |
function getKey(tag, callback) { | |
getAccountName(function(accountName) { | |
if (!accountName) { | |
error("Couldn't get your account name."); | |
return; | |
} | |
var identitySecret = storage.getValue(accountName + ":identity_secret"); | |
if (!identitySecret || !identitySecret.length) { | |
error("Couldn't get your identity secret."); | |
return; | |
} | |
var time = Math.round(Date.now() / 1000); | |
var key = getConfirmationKey(identitySecret, time, tag); | |
callback(time, key); | |
}); | |
} | |
function getConfirmationKey(identitySecret, time, tag) { | |
var requiredLength = 8; | |
if (tag) { | |
if (tag.length > 32) { | |
requiredLength += 32; | |
} else { | |
requiredLength += tag.length; | |
} | |
} | |
var buffer = new Uint8Array(requiredLength); | |
for (var idx = 7; idx >= 0; --idx) { | |
buffer[idx] = time & 0xFF; | |
time >>>= 8; | |
} | |
if (tag) { | |
tag = Array.from(tag, function(c){return c.charCodeAt(0)}); | |
buffer.set(tag, 8); | |
} | |
buffer = Array.from(buffer, function(n){return n.toString(16).padStart(2, '0')}).join(''); | |
var hash = CryptoJS.HmacSHA1(CryptoJS.enc.Hex.parse(buffer), CryptoJS.enc.Base64.parse(identitySecret)); | |
return hash.toString(CryptoJS.enc.Base64); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment