mirror of
https://github.com/iv-org/invidious.git
synced 2025-07-10 06:05:47 -05:00
Add support for encrypted query parameters
This commit is contained in:
parent
df8839d1f0
commit
f5aa881324
@ -568,6 +568,21 @@ hmac_key: "CHANGE_ME!!"
|
|||||||
##
|
##
|
||||||
#playlist_length_limit: 500
|
#playlist_length_limit: 500
|
||||||
|
|
||||||
|
##
|
||||||
|
## Encrypts query params 'ip' and 'pot'
|
||||||
|
## This is useful if you don't want to leak the IP address
|
||||||
|
## and PoToken used when fetching a Youtube video.
|
||||||
|
##
|
||||||
|
## Note: This will only work if the 'Proxy videos' preference is enabled
|
||||||
|
## on the Player preferences. Users that do not have 'Proxy videos' enabled
|
||||||
|
## will be able to see the IP address and PoToken used on videoplayback
|
||||||
|
## requests.
|
||||||
|
##
|
||||||
|
## Accepted values: true, false
|
||||||
|
## Default: false
|
||||||
|
##
|
||||||
|
#encrypt_query_params: false
|
||||||
|
|
||||||
#########################################
|
#########################################
|
||||||
#
|
#
|
||||||
# Default user preferences
|
# Default user preferences
|
||||||
|
@ -183,6 +183,8 @@ class Config
|
|||||||
# Playlist length limit
|
# Playlist length limit
|
||||||
property playlist_length_limit : Int32 = 500
|
property playlist_length_limit : Int32 = 500
|
||||||
|
|
||||||
|
property encrypt_query_params : Bool = false
|
||||||
|
|
||||||
def disabled?(option)
|
def disabled?(option)
|
||||||
case disabled = CONFIG.disable_proxy
|
case disabled = CONFIG.disable_proxy
|
||||||
when Bool
|
when Bool
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
require "uri/params/serializable"
|
||||||
|
|
||||||
# See http://www.evanmiller.org/how-not-to-sort-by-average-rating.html
|
# See http://www.evanmiller.org/how-not-to-sort-by-average-rating.html
|
||||||
def ci_lower_bound(pos, n)
|
def ci_lower_bound(pos, n)
|
||||||
if n == 0
|
if n == 0
|
||||||
@ -384,12 +386,17 @@ def parse_link_endpoint(endpoint : JSON::Any, text : String, video_id : String)
|
|||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
def encrypt_ecb_without_salt(data, key)
|
def ecb_without_salt(data : String, key : String, mode : Symbol)
|
||||||
cipher = OpenSSL::Cipher.new("aes-128-ecb")
|
cipher = OpenSSL::Cipher.new("aes-128-ecb")
|
||||||
cipher.encrypt
|
case mode
|
||||||
|
when :encrypt
|
||||||
|
cipher.encrypt
|
||||||
|
when :decrypt
|
||||||
|
cipher.decrypt
|
||||||
|
end
|
||||||
cipher.key = key
|
cipher.key = key
|
||||||
|
|
||||||
io = IO::Memory.new
|
io = IO::Memory.new(data.bytesize + 16)
|
||||||
io.write(cipher.update(data))
|
io.write(cipher.update(data))
|
||||||
io.write(cipher.final)
|
io.write(cipher.final)
|
||||||
io.rewind
|
io.rewind
|
||||||
@ -399,6 +406,27 @@ end
|
|||||||
|
|
||||||
def invidious_companion_encrypt(data)
|
def invidious_companion_encrypt(data)
|
||||||
timestamp = Time.utc.to_unix
|
timestamp = Time.utc.to_unix
|
||||||
encrypted_data = encrypt_ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key)
|
encrypted_data = ecb_without_salt("#{timestamp}|#{data}", CONFIG.invidious_companion_key, :encrypt)
|
||||||
return Base64.urlsafe_encode(encrypted_data)
|
return Base64.urlsafe_encode(encrypted_data)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
struct PrivateParams
|
||||||
|
include URI::Params::Serializable
|
||||||
|
include JSON::Serializable
|
||||||
|
|
||||||
|
property ip : String = ""
|
||||||
|
property pot : String = ""
|
||||||
|
end
|
||||||
|
|
||||||
|
def encrypt_query_params(query_params : URI::Params) : String
|
||||||
|
private_params = PrivateParams.from_www_form(query_params.to_s).to_json
|
||||||
|
encrypted_data = ecb_without_salt(private_params, CONFIG.hmac_key, :encrypt)
|
||||||
|
return Base64.urlsafe_encode(encrypted_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def decrypt_query_params(query_param_data : String) : PrivateParams
|
||||||
|
query_param_data = Base64.decode_string(query_param_data)
|
||||||
|
decrypted_data = ecb_without_salt(query_param_data, CONFIG.hmac_key, :decrypt)
|
||||||
|
private_params = PrivateParams.from_json(decrypted_data)
|
||||||
|
return private_params
|
||||||
|
end
|
||||||
|
@ -9,6 +9,13 @@ module Invidious::HttpServer
|
|||||||
|
|
||||||
# Add some URL parameters
|
# Add some URL parameters
|
||||||
params = url.query_params
|
params = url.query_params
|
||||||
|
if CONFIG.encrypt_query_params
|
||||||
|
encrypted_data = encrypt_query_params(params)
|
||||||
|
params["enc"] = "true"
|
||||||
|
params["data"] = encrypted_data
|
||||||
|
params.delete("ip")
|
||||||
|
params.delete("pot")
|
||||||
|
end
|
||||||
params["host"] = url.host.not_nil! # Should never be nil, in theory
|
params["host"] = url.host.not_nil! # Should never be nil, in theory
|
||||||
params["region"] = region if !region.nil?
|
params["region"] = region if !region.nil?
|
||||||
url.query_params = params
|
url.query_params = params
|
||||||
|
@ -4,6 +4,14 @@ module Invidious::Routes::VideoPlayback
|
|||||||
locale = env.get("preferences").as(Preferences).locale
|
locale = env.get("preferences").as(Preferences).locale
|
||||||
query_params = env.params.query
|
query_params = env.params.query
|
||||||
|
|
||||||
|
if query_params["enc"]? == "true"
|
||||||
|
decrypted_data = decrypt_query_params(query_params["data"])
|
||||||
|
query_params["ip"] = decrypted_data.ip
|
||||||
|
query_params["pot"] = decrypted_data.pot
|
||||||
|
query_params.delete("enc")
|
||||||
|
query_params.delete("data")
|
||||||
|
end
|
||||||
|
|
||||||
fvip = query_params["fvip"]? || "3"
|
fvip = query_params["fvip"]? || "3"
|
||||||
mns = query_params["mn"]?.try &.split(",")
|
mns = query_params["mn"]?.try &.split(",")
|
||||||
mns ||= [] of String
|
mns ||= [] of String
|
||||||
|
Loading…
x
Reference in New Issue
Block a user