Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Welcome to our site

Take a moment to join our board


RC5 Package - Go

Recommended Posts

I had help from @Spirited to figure this stuff out and port it to Go. I know a lot of people in the emulator communities don't use Go, but I hope with more packages released it will lift the barrier for people to use it.

It's pretty straight forward, use the NewRC5 method instead of a struct literal. Encrypt by calling Encrypt and supplying a dst byte slice the same size as the src slice. For Decrypting, do the same thing.

This adheres to the Cipher.Block interface, so for your client/conn structs you can just use that interface type.


package rc5

import (

const (
	WordSize = 16
	Rounds   = 12
	KeySize  = WordSize / 4
	SubSize  = 2 * (Rounds + 1)

type RC5 struct {
	Key []uint32
	Sub []uint32

func NewRC5() RC5 {
	c := RC5{}

	c.Key = make([]uint32, KeySize)
	c.Sub = make([]uint32, SubSize)
	//Conquer default key
		0x3C, 0xDC, 0xFE, 0xE8, 0xC4, 0x54, 0xD6, 0x7E,
		0x16, 0xA6, 0xF8, 0x1A, 0xE8, 0xD0, 0x38, 0xBE,

	return c

func (r *RC5) generateKeys(buf []byte) {
	//Initialize key expansion
	//seedLength := len(buf) / WordSize * WordSize
	for i := 0; i < KeySize; i++ {
		r.Key[i] = binary.LittleEndian.Uint32(buf[i*4:])

	//Generate r.Sub
	r.Sub[0] = 0xB7E15163
	for i := 1; i < SubSize; i++ {
		r.Sub[i] = r.Sub[i-1] - 0x61C88647

	//Generate key vector
	var a, b uint32
	var i, j int

	for x := 0; x < 3*SubSize; x++ {
		r.Sub[i] = bits.RotateLeft32(r.Sub[i]+(a+b), 3)
		a = r.Sub[i]
		r.Key[j] = bits.RotateLeft32(r.Key[j]+(a+b), int(a+b))
		b = r.Key[j]

		i = (i + 1) % SubSize
		j = (j + 1) % KeySize

func (r *RC5) Encrypt(dst, src []byte) {
	length := len(src) / 8
	if (len(src) % 8) > 0 {
		length = length + 1
	copy(dst, src)

	for word := 0; word < length; word++ {
		a := binary.LittleEndian.Uint32(dst[8*word:]) + r.Sub[0]
		b := binary.LittleEndian.Uint32(dst[(8*word + 4):]) + r.Sub[1]

		for round := 1; round <= Rounds; round++ {
			a = bits.RotateLeft32(a^b, int(b)) + r.Sub[2*round]
			b = bits.RotateLeft32(b^a, int(a)) + r.Sub[2*round+1]

		binary.LittleEndian.PutUint32(dst[8*word:], a)
		binary.LittleEndian.PutUint32(dst[8*word+4:], b)


func (r *RC5) Decrypt(dst, src []byte) {
	length := len(src) / 8
	if (len(src) % 8) > 0 {
		length = length + 1
	copy(dst, src)

	for word := 0; word < length; word++ {
		a := binary.LittleEndian.Uint32(dst[8*word:])
		b := binary.LittleEndian.Uint32(dst[(8*word)+4:])

		for round := Rounds; round > 0; round-- {
			b = bits.RotateLeft32(b-r.Sub[2*round+1], -int(a)) ^ a
			a = bits.RotateLeft32(a-r.Sub[2*round], -int(b)) ^ b

		binary.LittleEndian.PutUint32(dst[8*word:], a-r.Sub[0])
		binary.LittleEndian.PutUint32(dst[8*word+4:], b-r.Sub[1])

func BlockSize() int {
	return 8


Edited by W1cked
  • Like 1

Share this post

Link to post
Share on other sites

Looks good. Btw, I recommend taking a look at Visual Studio Code and the Go extension for it. It'll automatically help you lint your code using downloaded tools (like golint). I use it on my project, and it reminds me to add comment blocks to functions and reduce package naming redundancies. It's been a really useful tool to have while learning Go. Anyways, thanks for the contribution - looks very nice.

Share this post

Link to post
Share on other sites

Thanks! I use Goland, but I don't think I have golint on it. Thank you for the tip!

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By Spirited
      Comet is a Conquer Online server project containing an account server and game server. The account server authenticates players, while the game server services players in the game world. This simple two-server architecture acts as a good introduction into server programming and networking. The server is interoperable with the Conquer Online game client, patch 5017 (not provided by this project).
      This project was initially created for an interview as a 3-week programming project. Now, it's a base source that I'm opening up to the community. Feel free to add to it and submit push requests. I'm mostly active on my GitLab account, but feel free to hit me up here if I don't get to things soon enough.
      Source Control: https://gitlab.com/spirited/comet
      Readme: https://gitlab.com/spirited/comet/blob/master/Readme.md
      Issue Tracker: https://gitlab.com/spirited/comet/issues
      Storyboard: https://trello.com/b/tb8ChBlF/comet 
    • By Spirited
      Lines is a cross-platform system administration and software automation toolkit, leveraging golang for networking and parallel tasks. Command-line tools under Lines each focus on a task that can be performed in parallel, yielding faster results and offering some unique functionality. It's a project I got started to help accelerate some tasks at work and test Conquer Online servers. To get started, download the release binaries or build from source using the instructions below. I'll be adding to it as I go. Check out my Trello for some of the ideas I have.
      Build Instructions
      To build from source, run the following commands. Building requires the Golang compiler for lines source code, and goutil tools for code generation of system calls (fetched in the commands below).
      go get -u -d -v warry.io/lines/... go install -v warry.io/lines/... Tools
      exec: runs programs and clocks the overall execution time fetch: sends an HTTP GET request post: sends an HTTP POST request with either a form or file body serve: serves a file system using a web server multiplexer Links
      Github: https://github.com/garethwarry/lines
      Trello: https://trello.com/b/MxoRqm0H/lines

Important Information

By using this site, you agree to our Terms of Use.