UWP MediaPlayer : Play encrypted HLS stream by passing the key from app - encryption

I am looking for a way to play the encrypted HLS streams in UWP MediaElement , I am able to play the url that has key url given but I need to pass the key from app, not from the key url.
#EXT-X-KEY:METHOD=AES-128,URI="stream.m3u8.key",IV=0x00000000000000000000000000000000
IF the key file is present the below code works fine.
async private void InitializeAdaptiveMediaSource(System.Uri uri)
{
AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(uri);
if (result.Status == AdaptiveMediaSourceCreationStatus.Success)
{
ams = result.MediaSource;
mediaPlayerElement.SetMediaPlayer(new Windows.Media.Playback.MediaPlayer());
mediaPlayerElement.MediaPlayer.Source = MediaSource.CreateFromAdaptiveMediaSource(ams);
mediaPlayerElement.MediaPlayer.AutoPlay = true;
mediaPlayerElement.Stretch = Microsoft.Toolkit.Win32.UI.Controls.Interop.WinRT.Stretch.Uniform;
ams.InitialBitrate = ams.AvailableBitrates.Max<uint>();
//Register for download requests
ams.DownloadRequested += DownloadRequested;
////Register for download failure and completion events
//ams.DownloadCompleted += DownloadCompleted;
//ams.DownloadFailed += DownloadFailed;
////Register for bitrate change events
//ams.DownloadBitrateChanged += DownloadBitrateChanged;
//ams.PlaybackBitrateChanged += PlaybackBitrateChanged;
////Register for diagnostic event
//ams.Diagnostics.DiagnosticAvailable += DiagnosticAvailable;
}
else
{
//// Handle failure to create the adaptive media source
//MyLogMessageFunction($"Adaptive source creation failed: {uri} - {result.ExtendedError}");
}
}
But I want to pass the key from my app to decrypt the video and play in the MediaElement.Any help regarding this is greatly appriciated.

Related

How to create user interface for server hosted on esp32

I have a esp32 in my home which i have programmed for controlling some christmas lights. I have set up a http server on it connected to my home wifi, and can control it by sending http requests to 10.0.0.22 using either the web browser or postman.
I would prefer to be able to make post requests and control the request body from the ui.
I do not have any other server in my home, and do not want to expose the esp32 to anything outside my home wifi.
What is a good way to build a ui for the lights where i do not hit these issues?
When i try make a UI using e.g. javascript i get hit by a a bunch of security walls (understandably). I tried using flutter, and it works in dev, but when i installed the apk to an android phone it stopped working. In flutter i used the http library.
You could make an android app, is fairly simple, then you could make a json string and send it as a POST html message from android app, to the local IP of the ESP32. I made a code similar a time ago and looks something like this:
ui.button.setOnClickListener {
ui.visorTexto.setText("")
//val url = "http://192.168.100.235"
val url = ui.urlTexto.text.toString()
val jsonBody = JSONObject()
//val valorPin = ui.pinTexto.text.toString().toIntOrNull()
//val valorEstado = ui.estadoTexto.text.toString().toIntOrNull()
val valorPin = 1
val valorEstado = 1000
if (valorPin != null) {
if(valorPin in 0..13){
if (valorEstado != null) {
if(valorEstado >= 0 && valorEstado <= 2000){
jsonBody.put("opcion", valorPin.toString())
jsonBody.put("tiempo", valorEstado.toString())
val jsonObjectRequest = JsonObjectRequest(Request.Method.POST, url, jsonBody,
{ response -> ui.visorTexto.setText(response.toString())}
) { error -> ui.visorTexto.setText(error.printStackTrace().toString()) }
jsonObjectRequest.retryPolicy = DefaultRetryPolicy(
10000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT
)
val cache = DiskBasedCache(cacheDir, 1024 * 1024) // 1MB cap
val network = BasicNetwork(HurlStack())
var requestQueue = RequestQueue(cache, network).apply {
start()
}
requestQueue.add(jsonObjectRequest)
} else{
ui.visorTexto.setText("Error el estado es incorrecto: ${valorEstado}")
}
}
else{
ui.visorTexto.setText("Error2")
}
} else{
ui.visorTexto.setText("Error el rango de pin es incorrecto")
}
}
else{
ui.visorTexto.setText("Error1 ${valorPin}")
}
}
The user interface on android studio just have a button, and the options to make a led on or off, any of the digital pins of the ESP32. I used kotling and Android Studio Dolphin.

Are websocket, playing audio in background, and storing files locally possible in KaiOS app?

I am planning to develop a chat and voice messaging app in KaiOS, but want to make sure whether these things are possible in KaiOS:
web sockets in background (can receive the data when app is not opened)
playing audio in background without user interaction
storing files locally
Web Sockets : Web sockets can work only if the app is at foreground. You can use window.MozWebSocket or websock.js.
If you want to do any data exchange activity in background, then make use of push notification, serviceworker and indexed db/cache API.
Storing files : Yes you can read and write files
To read,
var sdcard = navigator.getDeviceStorage('sdcard');
var request = sdcard.get("fileName");
request.onsuccess = function () {
var fileObject = this.result;
};
request.onerror = function () {
console.warn("Unable to get the file: " + this.error);
};
To write,
var sdcard = navigator.getDeviceStorage("sdcard");
var request = sdcard.addNamed("file data", "test.txt");
request.onsuccess = function () {
var name = this.result;
console.log('File "' + name + '" successfully wrote !!');
};
request.onerror = function () {
console.warn('Unable to write the file: ' + this.error);
}
Background WebSockets aren't supposed by any browser, or on KaiOS. You can use Web Push to receive push notifications in the background.
Background audio playback is supported
Files can be read and saved locally using the Device Storage API

NSFileProtectionComplete doesn't encrypt the core data file

I am using Xcode 7.3 for iOS 9.3 to try and encrypt a Core Data file. I am trying to use NSPersistentStoreFileProtectionKey and set it to NSFileProtectionComplete to enable the encryption. It is not working for some reason and I can always see the .sqlite file generated by the app and browse through the content in sqlitebrowser or iexplorer. Here is my code :
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
// Create the coordinator and store
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
var failureReason = "There was an error creating or loading the application's saved data."
let dict: [NSObject : AnyObject] = [
NSPersistentStoreFileProtectionKey : NSFileProtectionComplete
]
do {
try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: dict)
} catch {
// Report any error we got.
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error as NSError
let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
abort()
}
do {
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
try NSFileManager.defaultManager().setAttributes([NSFileProtectionKey : NSFileProtectionComplete], ofItemAtPath: url.path!)
} catch {
}
do {
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite-wal")
try NSFileManager.defaultManager().setAttributes([NSFileProtectionKey : NSFileProtectionComplete], ofItemAtPath: url.path!)
// try print(NSFileManager.defaultManager().attributesOfFileSystemForPath(String(url)))
} catch {
}
do {
let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite-shm")
try NSFileManager.defaultManager().setAttributes([NSFileProtectionKey : NSFileProtectionComplete], ofItemAtPath: url.path!)
// try print(NSFileManager.defaultManager().attributesOfFileSystemForPath(String(url)))
} catch {
}
return coordinator
}()
I have also enabled Data Protection for my target in the "Capabilities". I have regenerated the provisioning profile from the Apple Developer portal and am using that with Enabled Data Protection.
I am also using the following code to check the file attributes of .sqlite , .sqlite-wal and .sqlite-shm files. NSFileProtectionKey is correctly set for all 3 of them.
func checkProtectionForLocalDb(atDir : String){
let fileManager = NSFileManager.defaultManager()
let enumerator: NSDirectoryEnumerator = fileManager.enumeratorAtPath(atDir)!
for path in enumerator {
let attr : NSDictionary = enumerator.fileAttributes!
print(attr)
}
}
I also tried disabling the Journal mode to prevent -wal and -shm files from being created. But I can still read the .sqlite file. Even though the attributes read NSFileProtectionComplete.
As described in the Apple Documentation at Apple Docs under "Protecting Data using On Disk Encryption", I tried to check whether the value of variable protectedDataAvailable changes as shown in the code below
public func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
NSThread.sleepForTimeInterval(10)
sleep(10)
let dataAvailable : Bool = UIApplication.sharedApplication().protectedDataAvailable
print("Protected Data Available : " + String(dataAvailable))
}
If I check the value without the delay it's set to true but after adding the delay it's set to false. This is kind of encouraging, however, right after, when I download the container, to show the content, it still has .sqlite file that still shows the content when opened in sqlitebrowser.
Ok, I finally understand this.
Using Xcode 7.3.1
Enabling File Protection
Enable File Protection using the Capabilities tab on your app target
If you do not want the default NSFileProtectionComplete, change this setting in the developer portal under your app id
Make sure Xcode has the new provisioning profile this creates.
For protecting files your app creates, that's it.
To protect Core Data, you need to add the NSPersistentStoreFileProtectionKey: NSFileProtectionComplete option to your persistent store.
Example:
var options: [NSObject : AnyObject] = [NSMigratePersistentStoresAutomaticallyOption: true,
NSPersistentStoreFileProtectionKey: NSFileProtectionComplete,
NSInferMappingModelAutomaticallyOption: true]
do {
try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options)
Testing File Protection
I am not able to test this using a non-jailbroken device connected to a computer. Every attempt to access the device this way requires that I "trust" the computer and I believe that trusted computers are always able to read the phone's data ("Trusted computers can sync with your iOS device, create backups, and access your device's photos, videos, contacts, and other content" - https://support.apple.com/en-us/HT202778). I think the other answers on SO referencing this technique are no longer valid with more recent versions of iOS. Indeed, I am always able to download the container using XCode and view the app's data using iPhone Explorer. So how to test...
1 - Create an archive and ensure that it is has the proper entitlements by running the following on the .app file from the command line:
codesign -d --entitlements :- <path_to_app_binary>
You should see a key/value pair that represents your Data Protection level. In this example, NSFileProtectionComplete:
<key>com.apple.developer.default-data-protection</key>
<string>NSFileProtectionComplete</string>
In addition, I used the following two techniques to satisfy myself that the data protection is indeed working. They both require code changes.
2 - Add some code to verify that the proper NSFileProtectionKey is being set on your files and/or core data store:
NSFileManager.defaultManager().attributesOfItemAtPath(dbPath.path!)
If I print this out on one of my files I get:
["NSFileCreationDate": 2016-10-14 02:06:39 +0000, "NSFileGroupOwnerAccountName": mobile, "NSFileType": NSFileTypeRegular, "NSFileSystemNumber": 16777218, "NSFileOwnerAccountName": mobile, "NSFileReferenceCount": 1, "NSFileModificationDate": 2016-10-14 02:06:39 +0000, "NSFileExtensionHidden": 0, "NSFileSize": 81920, "NSFileGroupOwnerAccountID": 501, "NSFileOwnerAccountID": 501, "NSFilePosixPermissions": 420, "NSFileProtectionKey": NSFileProtectionComplete, "NSFileSystemFileNumber": 270902]
Note the "NSFileProtectionKey": "NSFileProtectionComplete" pair.
3 - Modify the following code and hook it up to some button in your app.
#IBAction func settingButtonTouch(sender: AnyObject) {
updateTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self,
selector: #selector(TabbedOverviewViewController.runTest), userInfo: nil, repeats: true)
registerBackgroundTask()
}
var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
var updateTimer: NSTimer?
func registerBackgroundTask() {
backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
[unowned self] in
self.endBackgroundTask()
}
assert(backgroundTask != UIBackgroundTaskInvalid)
}
func endBackgroundTask() {
NSLog("Background task ended.")
UIApplication.sharedApplication().endBackgroundTask(backgroundTask)
backgroundTask = UIBackgroundTaskInvalid
}
func runTest() {
switch UIApplication.sharedApplication().applicationState {
case .Active:
NSLog("App is active.")
checkFiles()
case .Background:
NSLog("App is backgrounded.")
checkFiles()
case .Inactive:
break
}
}
func checkFiles() {
// attempt to access a protected resource, i.e. a core data store or file
}
When you tap the button this code begins executing the checkFiles method every .5 seconds. This should run indefinitely with the app in the foreground or background - until you lock your phone. At that point it should reliably fail after roughly 10 seconds - exactly as described in the description of NSFileProtectionComplete.
We need to understand how Data Protection works.
Actually, you don't even need to enable it. Starting with iOS7, the default protection level is “File Protection Complete until first user authentication.”
This means that the files are not accessible until the user unlocks the device for the first time. After that, the files remain accessible even when the device is locked and until it shuts down or reboots.
The other thing is that you're going to see the app's data on a trusted computer always - regardless of the Data Protection level setting.
However, the data can’t be accessed if somebody tries to read them from the flash drive directly. The purpose of Data Protection is to ensure that sensitive data can’t be extracted from a password-protected device’s storage.
After running this code, I could still access and read the contents written to protectedFileURL, even after locking the device.
do {
try data.write(to: protectedFileURL, options: .completeFileProtectionUnlessOpen)
} catch {
print(error)
}
But that's normal since I ran iExplorer on a trusted computer.
And for the same reason, it's fine if you see your sqlite file.
The situation is different if your device gets lost or stolen. A hacker won't be able to read the sqlite file since it's encrypted. Well, unless he guesses your passcode somehow.
Swift 5.0 & Xcode 11:
Enable "Data Protection" in "Capabilities".
Use the following code to protect a file or folder at a specific path:
// Protects a file or folder + excludes it from backup.
// - parameter path: Path component of the file.
// - parameter fileProtectionType: `FileProtectionType`.
// - returns: True, when protected successful.
static func protectFileOrFolderAtPath(_ path: String, fileProtectionType: FileProtectionType) -> Bool {
guard FileManager.default.fileExists(atPath: path) else { return false }
let fileProtectionAttrs = [FileAttributeKey.protectionKey: fileProtectionType]
do {
try FileManager.default.setAttributes(fileProtectionAttrs, ofItemAtPath: path)
return true
} catch {
assertionFailure("Failed protecting path with error: \(error).")
return false
}
}
(Optional) Use the following code to check whether the file or folder at the specific path is protected (note: This only works on physical devices):
/// Returns true, when the file at the provided path is protected.
/// - parameter path: Path of the file to check.
/// - note: Returns true, for simulators. Simulators do not have hardware file encryption. This feature is only available for real devices.
static func isFileProtectedAtPath(_ path: String) -> Bool {
guard !Environment.isSimulator else { return true } // file protection does not work on simulator!
do {
let attributes = try FileManager.default.attributesOfItem(atPath: path)
if attributes.contains(where: { $0.key == .protectionKey }) {
return true
} else {
return false
}
} catch {
assertionFailure(String(describing: error))
return false
}
}
Rather than encrypt a file at the local level I set NSFileProtectionComplete for the app as a whole.
Create the file 'entitlements.plist' in your apps root folder with the following content.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>DataProtectionClass</key>
<string>NSFileProtectionComplete</string>
</dict>
</plist>
Then if you haven't already done so already (this could be the problem with your file level encryption) enable Data Protection in your apps capabilities.

Load a webpage that requires basic authentication in a Windows 8 App

How would you load an external site that requires basic authentication inside an iframe in a Windows 8 HTML/JavaScript app?
I've found that you can't use URLs of the form http://username:password#host/.
In order to load the URL I was trying to load, I had to use a webview or x-ms-webview and invoke it's navigateWithHttpRequestMessage function in order to pass the basic authentication header.
This resulted in the following code structure:
function ready(element, options) {
var webview = document.querySelector('[data-hook~="camera"]');
webview.navigateWithHttpRequestMessage(buildRequest());
}
function buildRequest() {
var username = 'username',
password = 'password',
Crypto = Windows.Security.Cryptography,
Http = Windows.Web.Http,
request,
buffer,
token;
request = new Http.HttpRequestMessage(
Http.HttpMethod.get,
new Windows.Foundation.Uri('http://ipcamera/'));
buffer = Crypto.CryptographicBuffer.convertStringToBinary(
[username, password].join(':'),
Crypto.BinaryStringEncoding.utf8);
token = Crypto.CryptographicBuffer.encodeToBase64String(buffer);
request.headers.authorization = new Http.Headers.HttpCredentialsHeaderValue('basic', token);
return request;
}
The caveat to this is that none of the DOM ready events seem to fire, so if you need to interact with the external site, you'll have to play with timers.

Worklight 6.2 - Broadcast notification not being sent

We are trying to run the sample app for push notifications with some modification to get it to send out a broadcast notification, but it is not getting sent.
We have modified the PushBackendEmulator code as well. The emulator invokes the submitBroadCastNotification procedure successfully and the following result is returned:
Server response :: /-secure-{"result":"Notification sent to all
users","isSuccessful":true}/
However, it appears the WL.Server.sendMessage method is not sending the message and returns. I am not able to see the server side logs either after a thorough search on the liberty server except for the messages.log on the liberty server which shows the following when WL.Server.sendMessage is called.
ht.integration.js.JavaScriptIntegrationLibraryImplementation E
FWLSE0227E: Failed to send notification. Reason: FPWSE0009E: Internal
server error. No devices found [project worklight]
Here is the adapter code:
function submitBroadcastNotification( notificationText) {
var notification = {};
notification.message = {};
notification.message.alert = notificationText;
//notification.target = {};
//notification.target.tagNames = ['test'];
WL.Logger.debug("broadcast: " + notification.message.alert );
var delayTimeOut = **WL.Server.sendMessage**("PushNotificationsApp", notification);
WL.Logger.debug("Return value from WL.Server.sendMessage :"+ delayTimeOut);
return {
result : "Notification sent to all users"
};
}
Here is the PushBackendEmulator code:
public static void main(String [] args){
String serverUrl =
"http://208.124.245.78:9080/worklight";
String notificationText = "Hellofrombroadcastingnotifications";
String userId = "admin";
notificationText = notificationText.replace(" ", "%20");
Logger.debug("sending broadcast notification: " + notificationText);
URL url = new URL(serverUrl
+ "/invoke?
adapter=PushAdapter&procedure=submitBroadcastNotification&parameters=['" + userId + "','" + notificationText + "']");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(10000);
connection.setDoOutput(true);
Logger.debug("Connected to server");
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = "";
String inputLine;
while ((inputLine = in.readLine()) != null)
response+= inputLine;
Logger.debug("response is:"+ response);
in.close();
Logger.debug("Server response :: " + response);
connection.disconnect();
Looking at your application from the PMR, it seems to me like you have mixed both event source-based notifications and broadcast notifications.
If you want to use Broadcast notifications, this means you cannot try imposing sending the notification to any specific userId, etc as it is not needed nor based on userIds.
By default, all devices are auto-subscribed to a tag called "push.ALL".
You can read more about broadcast notifications API methods in the IBM Worklight Knowledge Center.
This is a modified version of your application, tested in iOS and Android: https://www.dropbox.com/s/l2yk2pbvykrzfoh/broadcastNotificationsTest.zip?dl=0
Basically, I stripped away from it anything not related to broadcast notifications:
I removed the push securitytest from application-descriptor.xml
I removed any function from the adapter XML and JS files and main.js file that is related to event source-based notifications.
The end result is that after the app is loaded, you are right inside the application (no login).
I then right-clicked the adapter folder in Studio > invoke procedure, and selected the submitBroadcastNotification option to send the notification ("aaa").
In the device, a notification was received. Tapping it (if the app is closed) launches the application, which then triggers the WL.Client.Push.onMessage API in common\js\main.js to display alerts containing the payload and props of the received notification.
This was tested in both iOS and Android.
As the application was loading, I could see in LogCat and Xcode console the token registration.
To test this in iOS, you will need to update application-descriptor.xml with your own pushSender password and add your own apns-certificatae-sandbox.p12 file.
To test in Android, make sure you are have generated a browser key in the GCM console and are using it in application-descriptor.xml
For both, make sure that all requires ports and addresses and accessible in your network

Resources