kaltura / nginx-vod-module

NGINX-based MP4 Repackager
GNU Affero General Public License v3.0
1.99k stars 439 forks source link

Why can't I use Java spring services as the hls decryption method? #1460

Closed qwerfdg closed 1 year ago

qwerfdg commented 1 year ago

Hello! When I use nginx-vod-module to implement video services and HLS encryption to protect my video, I can only use php service as vod_hls_encryption_key_uri. Java Spring service uri seems can't be accepted by my video player. The following is a list of my running environment configurations. host OS: windows 10 docker desktop v4.20.1 docker images running nginx-vod-module: centos7.9.2009 nginx: nginx-1.20.1 nginx-vod-module: 91005e14a9055f16a916c3e9fa31ceb51292e926 docker images running nginx for proxy PHP: latest docker images running PHP: 7.1.0-fpm docker images running mysql for java spring: 5.7 Java spring service is running on my host machine and all containers are under the same docker net. Video Player: potplayer 200908(1.7.21295) or VLC media player 3.0.18 vetinari. Here is my nginx.conf

#user root;
worker_processes  1;
events {
    worker_connections  1024;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    server {
        listen       80;
        server_name  localhost;
        autoindex on;
        location /vod_aes {
            vod hls; 
            vod_mode local; 
            vod_hls_encryption_method aes-128; 
            vod_drm_enabled on;
            vod_drm_upstream_location /base64key;
            #vod_drm_request_uri /base64key.php; # php encode
            vod_drm_request_uri /secret_key; # java encode
            vod_hls_encryption_key_uri http://127.0.0.1:8880/base64key/decodeKey.php; # php decode
            #vod_hls_encryption_key_uri http://127.0.0.1:8763/decodekey; # java decode
            vod_align_segments_to_key_frames on; 
            add_header Access-Control-Allow-Headers '*';
            add_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';
            add_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';
            add_header Access-Control-Allow-Origin '*';
            alias /media; 
        }
        location /base64key {
            #proxy_pass http://172.18.0.1:8880;
            proxy_pass http://172.20.240.1:8763; # wsl ip
        }
        location /data {
            alias /media;
        }
        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

Here is my java spring' file jdbcController.java

package com.example.demo.Controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
import java.util.List;
import java.util.Base64;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import java.io.IOException;
@RestController
public class jdbcController {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @GetMapping("/base64key/secret_key")
    public String list(){
        String sql="select * from secret_key";
        List<Map<String,Object>> secret_key=jdbcTemplate.queryForList(sql);
        ObjectMapper mapper = new ObjectMapper();
        try {
            String json = mapper.writeValueAsString(secret_key);
            return json;
        } catch (JsonParseException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }
    @GetMapping("/decodekey")
    public String decodelist(){
        String sql="select `key` from secret_key";
        List<Map<String,Object>> secret_key=jdbcTemplate.queryForList(sql);
        Base64.Decoder decoder = Base64.getDecoder();
        String decoded = new String(decoder.decode(secret_key.get(0).get("key").toString()));
        return decoded;
    }
}

Here is my base64key.php and decodeKey.php

<?php
$str = '[{"key": "GzoNU9Dfwc//Iq3/zbzMUw==","key_id": "GzoNU9Dfwc//Iq3/zbzMUw=="}]';
echo $str;
?>
<?php
header('Access-Control-Allow-Origin:*'); 
header('Access-Control-Allow-Methods:OPTIONS, GET, POST'); 
header('Access-Control-Allow-Headers:x-requested-with'); 
$str = 'GzoNU9Dfwc//Iq3/zbzMUw==';
echo base64_decode($str);
?>

I can use encoding methods both java and php but decoding method only php. I haven't got any error meaage in error.log but only "[notice] 121#121: signal process started". And I can open any decode urls in the host's browser (http://127.0.0.1:8763/decodekey or http://127.0.0.1:8880/base64key/decodeKey.php) andI implemented a Python script to obtain the return values of two different urls to verify if they are consistent. I think my video player can obtain the correct decryption key whether I use Java or PHP services.

import requests
import re
response1 = requests.get('http://127.0.0.1:8880/base64key/decodeKey.php')
response2 = requests.get('http://127.0.0.1:8763/decodekey')
print(response1.text.encode('utf-8'))
print(response2.text.encode('utf-8'))
pattern = re.compile("^" + response1.text + "$")
match = pattern.match(response2.text)
if match is not None:
    print("yes")
else:
    print("no")

So why I can use php vod_hls_encryption_key_uri instead of java one? Any help means a lot to me. Thanks!