Roku Developer Program

Developers and content creators—a complete solution for growing an audience directly.
cancel
Showing results for 
Search instead for 
Did you mean: 
dreamer2057
Level 7

SSL --cert --key options

Hello! How to use SSL connection with custom certificate and key?

CURL request:
curl https://serviceSmiley Tongueort --cacert cafile.pem --cert certificate.crt --key private_key.key


--cert certificate.crt --key private_key.key

Many different attempts with code like this didn't work:

http = CreateObject("roUrlTransfer")
port = CreateObject("roMessagePort")
http.SetUrl(url)
http.SetMessagePort(port)
http.SetRequest("POST")
http.AddHeader("Content-Type", "application/json")
http.AddHeader("X-Roku-Reserved-Dev-Id", "")
http.SetCertificatesFile("pkg:/source/certificate.crt")
http.InitClientCertificates()
http.RetainBodyOnError(true)


Options:

EnablePeerVerification(false{ or true })
EnableHostVerification(false{ or true })

in different combinations didn't help.
Sincerely, Sergey Shoshin, software developer.
0 Kudos
9 Replies
belltown
Level 7

Re: SSL --cert --key options

Can you be more specific about what you mean by "didn't work" and "didn't help"?
https://github.com/belltown/
0 Kudos
dreamer2057
Level 7

Re: SSL --cert --key options

"belltown" wrote:
Can you be more specific about what you mean by "didn't work" and "didn't help"?


Basic request:

http = CreateObject("roUrlTransfer")
port = CreateObject("roMessagePort")
http.SetUrl(url)
http.SetMessagePort(port)
http.SetRequest("POST")
http.AddHeader("Content-Type", "application/json")
http.AddHeader("X-Roku-Reserved-Dev-Id", "")
http.SetCertificatesFile("pkg:/source/certificate.crt")
http.InitClientCertificates()
http.RetainBodyOnError(true)

while num_retries > 0
if (http.AsyncPostFromString(""))
event = wait(timeout, http.GetPort())
if type(event) = "roUrlEvent"
dd = event.GetString()
code = event.GetResponseCode()
.....


code = event.GetResponseCode() - "-60"
Something like "cURL error 60: SSL certificate problem: unable to get local issuer certificate" i think.

Applying
http.EnableHostVerification(false)

didn't change the response, "-60"

Applying
http.EnablePeerVerification(false)

changes the response into another error:
Code: 400 Bad Request
400 The SSL certificate error.

When working with certificates in PC browsers:
-60 means host not verified, i think.

  1. Site Page opens

  2. Browser didn't find host certificate and says "untrusted"

  3. When we says "does not matter" (In pc "i undestand the risk, bla bla bla, continue anyway") and browser opens the site.

  4. In next time, the server asks "where your private certificate?".



    • a. we install certificate and browser gave it to the server ---- site opens

    • b. certificate missed ---- server says 400 Bad request, you didn't have the certificate.


So, roku do not send certificates for some reasons...
Sincerely, Sergey Shoshin, software developer.
0 Kudos
belltown
Level 7

Re: SSL --cert --key options

The first thing I'd check is that the certificates file exists and is where you expect it to be. Break into the debugger and type:

?readasciifile("pkg:/source/certificate.crt")

Then make sure it is formatted something like this:

GTE CyberTrust Global Root
==========================
-----BEGIN CERTIFICATE-----
MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg
Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG
A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz
MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL
Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0
IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u
sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql
HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID
AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW
M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF
NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
-----END CERTIFICATE-----

Thawte Server CA
================
-----BEGIN CERTIFICATE-----
MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE
AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j
b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV
BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u
c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG
A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0
ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl
/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7
1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR
MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J
GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ
GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc=
-----END CERTIFICATE-----

https://github.com/belltown/
0 Kudos
dreamer2057
Level 7

Re: SSL --cert --key options

The first thing I'd check is that the certificates file exists and is where you expect it to be. Break into the debugger and type:


Yes, it exists, reading function displays certificate content.

Then make sure it is formatted something like this:

Oh, i see, certificates should be joined in single file. But it doesn't help too.

my certificate.pem (documentation says that SetCertificatesFile (https://sdkdocs.roku.com/display/sdkdoc/roUrlTransfer) waits pem extension of file, however, i tried .crt too) content:


Private Certificate
===========================
-----BEGIN CERTIFICATE-----
{Private Certificate}
-----END CERTIFICATE-----

Private Certificate Key
===========================
-----BEGIN PRIVATE KEY-----
{Private Key}
-----END PRIVATE KEY-----

CA certificates
===========================
-----BEGIN CERTIFICATE-----
{Certificate}
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
{Certificate}
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
{Certificate}
-----END CERTIFICATE-----



Server still returns 400 status code with Bad request (Didn't see certificate).
At that, if I separate this content by three file (cafile, certificate, private_key) and invoke (on PC) curl like i wrote above, it will be work:
curl https://serviceSmiley Tongueort --cacert cafile.pem --cert certificate.crt --key private_key.key
Sincerely, Sergey Shoshin, software developer.
0 Kudos
belltown
Level 7

Re: SSL --cert --key options

Are you trying to do server authentication or client authentication?

If you're attempting server authentication then you don't need to call InitClientCertificates(), and you don't need to add the X-Roku-Reserved-Dev-Id header. They shouldn't do any harm; however they are only needed if you're doing client authentication (that is, if your server is trying to authenticate that the requests are coming from a legitimate Roku device). In this case, you'd also need to copy the Roku public key file (located in the SDK file: certificates\cacert.pem) to your server.

For server authentication, the only thing you should need on the Roku is the certificate chain for the signer of your server certificate. The file containing the certificate chain is the file specified in the call to SetCertificatesFile().

You don't need the server's public key file (I assume that's what you have in certificate.crt). When the Roku establishes an https connection, the firmware sends the Roku's public key (buried in the firmware) to the server. The server then responds with the server's public key. The Roku will use the server's public key that it got from the server for encrypting messages to the server that are decrypted by the server using the server's private key.

You absolutely should not need the server's private key for anything. (I assume that's your file, private_key.key.) The whole point of public key encryption is that everyone is allowed to know the server's public key, which they use to encrypt messages sent to the server, but only the server has access to the private key, which it uses to decrypt the messages.

The call to SetCertificatesFile() should specify a file containing the certificate chain used to verify the signature on the server's public key. For whichever Certificate Authority was used to sign the server's public key, there should be a certificate in this file. All the Certificate Authorities in turn used to sign that CA's certificate should also be in the certificate file, all the way up to the root Certificate Authority.

The certificate file should be in PEM format. The certificates corresponding to each Certificate Authority should be concatenated within this file, each one having this format:

-----BEGIN CERTIFICATE-----
MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg
Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG
A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz
MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL
Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0
IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u
sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql
HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID
AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW
M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF
NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
-----END CERTIFICATE-----

This curl command should work if your certificates' file and your server are set up correctly:

curl https://serviceSmiley Tongueort --cacert cafile.pem

If you're using an Apache server, for example, the location of the certificate chain file on the server is specified by the SSLCACertificateFile directive. A copy of this same file (if it's in PEM format, or converted to PEM format) should also work on your Roku as the file specified by SetCertificatesFile().

All of the above assumes that your server certificate was not signed by one of the commonly-known Certificate Authorities. If it was, then you should be able to just use the standard Roku CA bundle:
http.SetCertificatesFile ("common:/certs/ca-bundle.crt")

And if your server is using a self-signed certificate, use the server's self-signed certificate (converted to PEM format) as the certificates' file.
https://github.com/belltown/
0 Kudos
dreamer2057
Level 7

Re: SSL --cert --key options

Thanks, belltown, that you trying help me!

Are you trying to do server authentication or client authentication?


server authentication, i think. My server should ask (specially generated, private) certificate from roku. Only if it will be sent and passed, the server will allow to view responses.
like curl request:

curl https://serviceSmiley Tongueort --cacert cafile.pem --cert certificate.crt --key private_key.key

Only if I add --cert and --key options, my server sends right response.

In this case, you'd also need to copy the Roku public key file (located in the SDK file: certificates\cacert.pem) to your server.

Yes, i read it in documentation. And not did this at this moment, I will try soon.

(I assume that's your file, private_key.key

No, no. Its important part, it's private key for the certificate. if I remove --key option from curl, it will be broken.

This curl command should work if your certificates' file and your server are set up correctly:

Only with client authentication it will work. In my case, cert and key needed.
Sincerely, Sergey Shoshin, software developer.
0 Kudos
belltown
Level 7

Re: SSL --cert --key options

"dreamer2057" wrote:
Are you trying to do server authentication or client authentication?


server authentication, i think. My server should ask (specially generated, private) certificate from roku. Only if it will be sent and passed, the server will allow to view responses.

That sounds like client authentication to me. That is when the server attempts to authenticate the client's credentials, which is what you seem to be describing.

In that case you need to call InitClientCertificates() in your Roku channel (which it looks like you're already doing), AND ensure that the Roku's Public Key is installed on your server (which you are not doing yet).

Also, you can't supply your own Private Key when using client authentication for a Roku, as you can do with your curl command. Instead, you must use the Roku's Public Key, and install that on your server. I believe Apache uses the SSLCACertificateFile directive for this along with SSLVerifyClient require.

Another thing that might help you is to call event.GetFailureReason() to get a more descriptive reason for the error.
https://github.com/belltown/
0 Kudos
dreamer2057
Level 7

Re: SSL --cert --key options

That sounds like client authentication to me.

Yes, maybe. I mean server-side authentication Smiley Happy

Instead, you must use the Roku's Public Key, and install that on your server

I'll discuss it with our system adminitrators in the near future, probably today.

Thanks, I will write about the results.
Sincerely, Sergey Shoshin, software developer.
0 Kudos
dreamer2057
Level 7

Re: SSL --cert --key options

Ok, now it works. I add "RokuTV Certification Authority" certificate into the server.

So, the problem was in:

Also, you can't supply your own Private Key when using client authentication for a Roku, as you can do with your curl command.


I suppose to use personal certificate and private key. However, Roku's sertificate + private key + Pack ID in header + https request has enough security level to be quiet.


THANKS, belltown
Sincerely, Sergey Shoshin, software developer.
0 Kudos