diff --git a/i18n/de.json b/i18n/de.json index b40ff9b..de62e8f 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -159,5 +159,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/es.json b/i18n/es.json index 10cc7af..6dd9e91 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -159,5 +159,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/fr.json b/i18n/fr.json index d125b51..9b0a872 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -168,5 +168,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/hu.json b/i18n/hu.json index 5016db6..da2dd52 100644 --- a/i18n/hu.json +++ b/i18n/hu.json @@ -159,5 +159,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/it.json b/i18n/it.json index 2db8346..125812f 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -159,5 +159,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/nl.json b/i18n/nl.json index 35d540a..4c93d78 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -160,6 +160,6 @@ "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": "For more information see this FAQ entry.", - "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/no.json b/i18n/no.json index 1e19e4c..108ce8d 100644 --- a/i18n/no.json +++ b/i18n/no.json @@ -159,5 +159,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/oc.json b/i18n/oc.json index 8b745af..b9fac8f 100644 --- a/i18n/oc.json +++ b/i18n/oc.json @@ -168,5 +168,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/pl.json b/i18n/pl.json index 94f6d74..f1ae43f 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -159,5 +159,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/pt.json b/i18n/pt.json index 8db5fb8..f7b7e0b 100644 --- a/i18n/pt.json +++ b/i18n/pt.json @@ -159,5 +159,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." -} \ No newline at end of file + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." +} diff --git a/i18n/ru.json b/i18n/ru.json index c2b9edf..e084018 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -169,5 +169,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/sl.json b/i18n/sl.json index d34a9b9..e88961d 100644 --- a/i18n/sl.json +++ b/i18n/sl.json @@ -168,5 +168,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/i18n/zh.json b/i18n/zh.json index 8e01b2c..2e2c7de 100644 --- a/i18n/zh.json +++ b/i18n/zh.json @@ -159,5 +159,7 @@ "This website is using an insecure HTTP connection! Please use it only for testing.": "This website is using an insecure HTTP connection! Please use it only for testing.", "For more information see this FAQ entry.": - "For more information see this FAQ entry." + "For more information see this FAQ entry.", + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.": + "Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS." } diff --git a/js/privatebin.js b/js/privatebin.js index 64663d6..9bd336e 100644 --- a/js/privatebin.js +++ b/js/privatebin.js @@ -830,28 +830,13 @@ jQuery.PrivateBin = (function($, RawDeflate) { */ function getRandomBytes(length) { - if ( - typeof window !== 'undefined' && - typeof Uint8Array !== 'undefined' && - String.fromCodePoint && - ( - typeof window.crypto !== 'undefined' || - typeof window.msCrypto !== 'undefined' - ) - ) { - // modern browser environment - let bytes = ''; - const byteArray = new Uint8Array(length), - crypto = window.crypto || window.msCrypto; - crypto.getRandomValues(byteArray); - for (let i = 0; i < length; ++i) { - bytes += String.fromCharCode(byteArray[i]); - } - return bytes; - } else { - // legacy browser or unsupported environment - throw 'No supported crypto API detected, you may read pastes and comments, but can\'t create pastes or add new comments.'; + let bytes = ''; + const byteArray = new Uint8Array(length); + window.crypto.getRandomValues(byteArray); + for (let i = 0; i < length; ++i) { + bytes += String.fromCharCode(byteArray[i]); } + return bytes; } /** @@ -4537,36 +4522,6 @@ jQuery.PrivateBin = (function($, RawDeflate) { 'bot' ]; - /** - * blacklist of UserAgent versions known not to work with this application - * - * @private - * @enum {Object} - * @readonly - */ - const oldUA = [ - { - 'regex': /Chrome\/([0-9]+)/, - 'minVersion': 57, - }, - { - 'regex': /Edge\/([0-9]+)/, - 'minVersion': 16, - }, - { - 'regex': /Firefox\/([0-9]+)/, - 'minVersion': 54, - }, - { - 'regex': /Opera\/.*Version\/([0-9]+)/, - 'minVersion': 44, - }, - { - 'regex': /Version\/([0-9]+).*Safari/, - 'minVersion': 11, - } - ]; - /** * check if the connection is insecure * @@ -4602,7 +4557,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { // check whether a bot user agent part can be found in the current // user agent for (let i = 0; i < badBotUA.length; ++i) { - if (navigator.userAgent.indexOf(badBotUA) >= 0) { + if (navigator.userAgent.indexOf(badBotUA[i]) >= 0) { return true; } } @@ -4610,7 +4565,7 @@ jQuery.PrivateBin = (function($, RawDeflate) { } /** - * checks whether this is an unsupported browser + * checks whether this is an unsupported browser, via feature detection * * @private * @name InitialCheck.isOldBrowser @@ -4618,13 +4573,34 @@ jQuery.PrivateBin = (function($, RawDeflate) { * @return {bool} */ function isOldBrowser() { - for (let i = 0; i < oldUA.length; ++i) { - let result = oldUA[i]['regex'].exec(navigator.userAgent); - if (result && result[1] < oldUA[i]['minVersion']) { - return true; - } + // webcrypto support + if (typeof window.crypto !== 'object') { + return false; } - return false; + + if (typeof WebAssembly !== 'object' && typeof WebAssembly.instantiate !== 'function') { + return false; + } + try { + // [\0, 'a', 's', 'm', (uint_32) 1] - smallest valid wasm module + const module = new WebAssembly.Module(Uint8Array.of(0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00)); + if ( + !( + module instanceof WebAssembly.Module && + new WebAssembly.Instance(module) instanceof WebAssembly.Instance + ) + ) { + return false; + } + } catch (e) { + return false; + } + + // not checking for async/await, ES6, Promise or Uint8Array support, + // as most browsers introduced these earlier then webassembly and webcrypto: + // https://github.com/PrivateBin/PrivateBin/pull/431#issuecomment-493129359 + + return true; } /** @@ -4644,13 +4620,16 @@ jQuery.PrivateBin = (function($, RawDeflate) { } if (isOldBrowser()) { - $('#oldnotice').toggle(true); - // execution will likely fail, but the user agent may be - // deliberately set to an incorrect value, so let it proceed + // some browsers (Chrome based ones) would have webcrypto support if using HTTPS + if (isInsecureConnection()) { + Alert.showError(['Your browser may require an HTTPS connection to support the WebCrypto API. Try switching to HTTPS.', 'https' + window.location.href.slice(4)]); + } + $('#oldnotice').removeClass('hidden'); + return false; } if (isInsecureConnection()) { - $('#httpnotice').toggle(true); + $('#httpnotice').removeClass('hidden'); } return true; diff --git a/js/test/CryptTool.js b/js/test/CryptTool.js index 08e54eb..80ea5ec 100644 --- a/js/test/CryptTool.js +++ b/js/test/CryptTool.js @@ -10,7 +10,7 @@ describe('CryptTool', function () { this.timeout(30000); it('can en- and decrypt any message', function () { - jsc.check(jsc.forall( + jsc.assert(jsc.forall( 'string', 'string', 'string', @@ -193,7 +193,7 @@ describe('CryptTool', function () { }); it('can en- and decrypt a particular message (#260)', function () { - jsc.check(jsc.forall( + jsc.assert(jsc.forall( 'string', 'string', async function (key, password) { diff --git a/js/test/InitialCheck.js b/js/test/InitialCheck.js index 30aba1a..ce46f65 100644 --- a/js/test/InitialCheck.js +++ b/js/test/InitialCheck.js @@ -8,24 +8,66 @@ describe('InitialCheck', function () { cleanup(); }); - jsc.property( - 'returns false and shows error, if a bot UA is detected', - 'string', - jsc.elements(['Bot', 'bot']), - 'string', - function ( - prefix, botBit, suffix - ) { - const clean = jsdom( - '
', - {'userAgent': prefix + botBit + suffix} - ); - var result1 = $.PrivateBin.InitialCheck.init(), - result2 = !$('#errormessage').hasClass('hidden'); - clean(); - return result1 && result2; - } - ); + it('returns false and shows error, if a bot UA is detected', function () { + jsc.assert(jsc.forall( + 'string', + jsc.elements(['Bot', 'bot']), + 'string', + function (prefix, botBit, suffix) { + const clean = jsdom('', { + 'userAgent': prefix + botBit + suffix + }); + $('body').html( + '' + + '' + ); + $.PrivateBin.Alert.init(); + const result1 = !$.PrivateBin.InitialCheck.init(), + result2 = !$('#errormessage').hasClass('hidden'); + clean(); + return result1 && result2; + } + ), + {tests: 1}); + }); + + it('shows error, if no webcrypto is detected', function () { + [true, false].map( + function (secureProtocol) { + const clean = jsdom('', { + 'url': (secureProtocol ? 'https' : 'http' ) + '://[::1]/' + }); + $('body').html( + ''+ + '' + ); + const crypto = window.crypto; + window.crypto = null; + $.PrivateBin.Alert.init(); + assert(!$.PrivateBin.InitialCheck.init()); + assert(secureProtocol === $('#errormessage').hasClass('hidden')); + assert(!$('#oldnotice').hasClass('hidden')); + window.crypto = crypto; + clean(); + } + ); + }); + + it('shows error, if HTTP only site is detected', function () { + [true, false].map( + function (secureProtocol) { + const clean = jsdom('', { + 'url': (secureProtocol ? 'https' : 'http' ) + '://[::1]/' + }); + $('body').html( + '' + ); + assert($.PrivateBin.InitialCheck.init()); + assert(secureProtocol === $('#httpnotice').hasClass('hidden')); + clean(); + } + ); + }); }); }); diff --git a/js/test/ServerInteraction.js b/js/test/ServerInteraction.js index 6437737..21aa18d 100644 --- a/js/test/ServerInteraction.js +++ b/js/test/ServerInteraction.js @@ -9,7 +9,7 @@ describe('ServerInteraction', function () { }); this.timeout(30000); it('can prepare an encrypted paste', function () { - jsc.check(jsc.forall( + jsc.assert(jsc.forall( 'string', 'string', 'string', diff --git a/tpl/bootstrap.php b/tpl/bootstrap.php index ab39c7e..4871e2c 100644 --- a/tpl/bootstrap.php +++ b/tpl/bootstrap.php @@ -72,7 +72,7 @@ if ($MARKDOWN): endif; ?> - + diff --git a/tpl/page.php b/tpl/page.php index 436e013..8a32421 100644 --- a/tpl/page.php +++ b/tpl/page.php @@ -50,7 +50,7 @@ if ($MARKDOWN): endif; ?> - +