Reverse Engineering the Enphase Installer Toolkit

If you are interested in other Enphase information the following other pages may also be of interest:
Enphase Envoy-S “Data Scraping”.
Enphase Envoy-S Open Ports!

While on my quest to create my own logging and analytics for the Envoy-S Solar PV controller I also was interested in how the Installer Toolkit authenticates with the web interface of the Envoy.

Authentication is “Digest” based so it isn’t as simple as just undoing the base64 encoding that “Basic” http authentication uses. Digest uses a nonce, domain and url in the mix to make each request to different pages need it’s own hashed password.

The trouble is – I don’t know what the password is for the Envoy. The username is “installer” but the password isn’t something known. I hoped to extract the password generation method from the Android application.

What helped is the fact that it seems the application is a Xamarin based application. As far as I can work out this means they wrote the application in Microsoft Visual Studio and have ported it to run on multiple mobile devices (Apple, Android, Windows Phone(?)) using “Mono”. Mono is a Common Runtime Language (CRL) compiler? or runtime. I’ve written Visual Studio (vb.net) applications that run in linux using Mono.. very useful.

So – decompressing the APK produces a load of windows .dll files! ILSpy then allows me to investigate the content or code within.

ilspy xamarin enphase about box

So.. all easy for me to understand in the language(s) that I can work with.
Imagine my surprise when I came across the “Configuration” section.

enphase oauth 911wasaninsidejob Oauth1911wasaninsidejob

Private Const OAuth2BogusClientId As String = "installer-toolkit-bogus"

Private Const OAuth2BogusSecret As String = "911wasaninsidejob"

Private Const OAuth1BogusConsumerKey As String = "notavalidconsomerkey"

Private Const OAuth1BogusConsumerSecret As String = "Oauth1911wasaninsidejob"

While being part of code that isn’t used in active connections (I believe the bogus sections are for offline, debug or demonstration testing that don’t authenticate against live systems).. I’m amazed that wording like that has remained within a program written by a company who, I presume, wouldn’t like it against their reputation.

My first thought is maybe a programmer has taken example code and forgotten to change the strings.. but no, a quick Google Search doesn’t reveal any pages at all with the wording in it… so it isn’t a lazy copy and paste from existing public “example” code.

Moving on from that… Other interesting bits of code are:

Public Function UsernameIsReviewUser(username As String) As Boolean
    Return Not String.IsNullOrEmpty(username) AndAlso username.ToLower().Equals("enphase.rev1400@gmail.com")
End Function
Friend Module Crypto
    Private salt As Byte() = Encoding.ASCII.GetBytes("com.enphase-energy.rocksit247")

If you are on Android then the SQLite Database it uses is stored in “/mnt/sdcard/Enphase/EnphaseDB_fixed.db3”.

When the Envoy is in AP mode the IP address might be  “172.30.1.1”

Back onto Task. The Digest Authentication is handled by “Enphase.InstallerToolkit -> Enphase.Installeroolkit.Models -> EnphaseEnvoy” and uses the following code:

Public Sub SetupAuth()
	Dim credentialCache As CredentialCache = New CredentialCache()
	credentialCache.Add(New Uri("http://" + Me.IP_Address), "Digest", New NetworkCredential("installer", Me.GetPasswordForEnvoy()))
	credentialCache.Add(New Uri("http://" + Me.IP_Address + ":9094"), "Digest", New NetworkCredential("installer", Me.GetPasswordForEnvoy()))
	Dim nativeCookieHandler As NativeCookieHandler = New NativeCookieHandler()
	Dim list As List(Of Cookie) = New List(Of Cookie)()
	For Each current As Cookie In nativeCookieHandler.Cookies
		If current.Name.ToUpper().Equals("SESSIONID") Then
			current.Value = Nothing
			list.Add(current)
		End If
	Next
	nativeCookieHandler.SetCookies(list)
	Me.httpClient = New HttpClient(New NativeMessageHandler(False, False, nativeCookieHandler) With { .UseDefaultCredentials = False, .Credentials = credentialCache })
End Sub

Public Function GetPasswordForEnvoy() As String
	Dim bufLen As UInteger = 128UI
	Dim stringBuilder As StringBuilder = New StringBuilder(128)
	EnphaseEnvoy.emupwGetMobilePasswd(Me.Serial_Number, "installer", Nothing, stringBuilder, bufLen)
	Return stringBuilder.ToString()
End Function

Public Shared Declare Function emupwGetMobilePasswd Lib "libemupw.so" (in_serialNumber As String, in_user As String, in_domain As String, out_buf As StringBuilder, bufLen As UInteger) As Integer 

In plain terms this means the function “SetupAuth” adds credentials to the http request using the hard coded username “installer” and the password generated by the function ” GetPasswordForEnvoy”.

GetPasswordForEnvoy, as far as I can read, creates a 128 character buffer and string and then requests another function of “emupwGetMobilePasswd” with the parameters:
Serial Number of Envoy, “installer”, Nothing, Blank String, Blank Buffer

Now; emupwGetMobilePasswd then references to an external “libemupw.so”dependent which appears to be a compiled program or component for ARM architecture processors. Sadly it doesn’t seem to be a drop in component and is likely a custom file for Enphase
It only seems to take the serial number and username as input. The “Domain” string (3rd input) is set to “Nothing” in the code and the final two variables are the out string and buffer.

libemupw.cfg.emupwGetMobilePasswd

libemupw.cfg.emupwGetPasswd

libemupw.cfg.emupwGetPasswdForSn

This is where it gets beyond me skill level. I will continue to research and work out how I can either run the object on demand (to make a web service that people can type in a serial number and get back the password) or just the math or function used to hash the details to return the password. More to come.. Bookmark and return at some point.

Update: 19th November 2016. Version 2.1.10 of the Installer Toolkit is out and has the following notable changes.

It contains a variable WORK_OFFLINE_KEY

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

8 Responses to Reverse Engineering the Enphase Installer Toolkit

  1. RRM says:

    I’ll also bookmark this topic. Interesting progress you’re making!

  2. Paul says:

    yes – good info.

    Yet to try using the returned key with http outside of the installer ap.
    Could you post the format of the http command you were able to use?

    I have my own key.

  3. GET /api/v1/production/inverters HTTP/1.1
    Host: 10.0.0.177
    Connection: keep-alive
    Authorization: Digest username="installer", realm="enphaseenergy.com", nonce="XXXXXXXXXX", uri="/api/v1/production/inverters", response="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", qop=auth, nc=00000014, cnonce="XXXXXXXXXXXXXXXX"
    
    

    I expect the keep-alive line could be removed too.

  4. jam says:

    Well done! I took a similar path a few months ago, and got as far as decompiling the android app as well, resulting in extracting the dll files and that’s where I stopped as I don’t have a windows machine.

  5. Pingback: Enphase Envoy-S Open Ports! | thecomputerperson

  6. Pingback: Enphase Envoy-S “Data Scraping”. | thecomputerperson

  7. Al says:

    Well beyond my limited knowledge but I’m interested in what you’ve been able to achieve. I’m getting a Envoy S Metered installed in the next month and been pondering the ability to run a small pi box running a script to monitor the generation vs consumption to see what is excess and if over a certain threshold, close a dry contact that will operate a relay that will bring in the hot water system. Do you think this would be possible with what you’ve seen with the API? Or would it be easier to do it locally with CT clamps and measure local currents etc?

  8. Absolutely possible and I do it with a fab heater and an Omega Onion (similar to a pi). Just watch out for the envoy being laggy or crapping out under high load or many requests. See the comment thread about it queueing failed or timed out requests and snowballing. Make sure your script backs off and waits if the envoy doesn’t respond.

Comment on this topic

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s