📜 ⬆️ ⬇️

Updating services running on Go

I like to program on Go, but most of all now I like to program gobot for Raspberry Pi. Each change in the code requires some time for tedious operations associated with updating the code. First I have to stop the process, because Filezilla refuses to write to the executable file when the process is running, load a new executable file via SFTP and start it (this is not only tedious, but another 10-20 seconds of downtime when the process is stopped).

A similar situation haunts me when developing for a regular web on Go. It is in gobot that I have to update the code very often, which is connected with the style of development, which brings me pleasure in my free time. With the development of a new package to update the code written in Go has become easier and faster.

Now I will tell you how to use my package and how it works.

go get github.com/CossackPyra/updater 

This command has installed my updater in your Go, you can also install the tool on the command line with the following command:
')
 go get github.com/CossackPyra/updater/pyra-poster 

Here is an example of a web service with the ability to update:

 package main import ( "fmt" "io" "net/http" "os" "github.com/CossackPyra/updater" ) func main() { http.HandleFunc("/", handle_def) os.Mkdir("tmp", 0700) u1 := updater.UpdaterServer("tmp", []byte("1234567890123456"), os.Args[0]) http.Handle("/updater-me", u1) http.ListenAndServe(":9999", nil) } func handle_def(w http.ResponseWriter, r *http.Request) { fmt.Println("def ", r.Method) io.WriteString(w, "v 24\n") io.WriteString(w, r.URL.Path) println(r.URL.Path) } 

The following 3 lines add the ability to update the program:

  "github.com/CossackPyra/updater" ... u1 := updater.UpdaterServer("tmp", []byte("1234567890123456"), os.Args[0]) http.Handle("/updater-me", u1) 

In this case, everything is encrypted with a 16-byte key [] byte ("1234567890123456") , and 313233343536373393931313233343536 is its hexadecimal representation. new-service is a new executable file, and here is the command to update the old process.

 pyra-poster 31323334353637383930313233343536 new-service http://127.0.0.1:9999/updater-me 

How it works?


All code fit in 280 lines. I have more confidence in the code that I can quickly figure out. I’m not completely sure about the cryptographic strength of my encryption algorithm, and how I can be confident about something like that, so I’m interested to discuss it with you.

When initializing the handler in updater.UpdaterServer, a random sequence of 16 bytes is generated (rand1). In order to update the code, you must perform two requests to the handler. The first GET request receives these random 16 bytes (rand1). Random 16 bytes (rand1) and secret password (key1) are used to encrypt the executable file sent with the AES algorithm and send the cipher by POST.

First, the buffer is filled with the data according to the following recipe:
- Random 20 bytes (this is not rand1, but rand0 - at the moment they are not used at all);
- 20 bytes - sha1 executable file hash;
- “pyra-poster” - a sequence of bytes, the name of the protocol;
- 6 bytes (1 - int16 Little Endian, 0 - int32 Little Endian) - protocol version;
- the executable file itself.

This buffer is applied to the gamma function by the xor method, obtained by the block cipher AES (key1, rand1). The result is a ciphertext that is sent to the handler using the POST method.

On the server for decryption, the gamut AES (key1, rand1) is superimposed on the sequence, the pyra-poster header is checked (1.0), the executable file is saved in a temporary folder and the hash is calculated using the sha1 algorithm and compared with sha1 from the header. If the hashes are equal , then it can be assumed with high probability that this is an authentic file created by the owner of the service.

After updating the service, rand1 changes and therefore, having intercepted the ciphertext, it cannot be reloaded. It is also quite difficult to calculate key1, having rand1, and knowing the feature of the header “pyra-poster” (1,0) or even having an executable file.

The 16-byte (128-bit) key1 key can be replaced with a 32-byte (256-bit) key without any additional code changes. Most web browsers use AES 256 bit encryption.

Use on health.

Source: https://habr.com/ru/post/251031/


All Articles