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


Go RC5 Cipher Problems

Recommended Posts

Nevermind, I was nowhere close. I’ll repost when I make changes.

Edited by W1cked

Share this post

Link to post
Share on other sites

Hey Spirited, that’s actually what I tried to use initially. Then i tried to port CptSky’s but I think I was way off. I’ll post it again.


As for the Go package you posted, would it not work directly? I tried using it directly, but perhaps I was doing something wrong?

Edited by W1cked

Share this post

Link to post
Share on other sites

I'm not very well versed in C#, so some of the things I was porting I took guesses on.
Everything compiles, but the resulting bytes are definitely not correct.

For password "test" I get 

45 253 45 253 0 0 0 0 0 0 0 0 0 0 0 0

as a result after RC5 "decrypt"

Also, I can rewrite this to fit the cipher interface.  I do like that, and it is more "idiomatic" than mine is by far.

package rc5

import "errors"

const (
	RC5_PW32 = 0xB7E15163
	RC5_QW32 = 0x61C88647
	RC5_32   = 32
	RC5_12   = 12
	RC5_SUB  = RC5_12*2 + 2
	RC5_16   = 16
	RC5_KEY  = RC5_16 / 4

type RC5 struct {
	mKey [RC5_KEY]uint32
	mSub [RC5_SUB]uint32

/// CO2: { 0x3C, 0xDC, 0xFE, 0xE8, 0xC4, 0x54, 0xD6, 0x7E, 0x16, 0xA6, 0xF8, 0x1A, 0xE8, 0xD0, 0x38, 0xBE }
func NewRC5(seed []byte) (RC5, error) {
	c := RC5{}
	if len(seed) != 16 {
		return c, errors.New("seed does not have expected 16 bytes")

	for z := 0; z < RC5_KEY; z++ {
		c.mKey[z] = uint32(seed[z])

	c.mSub[0] = RC5_PW32
	for i := 1; i < RC5_SUB; i++ {
		c.mSub[i] = c.mSub[i-1] - RC5_QW32

	i, j, x, y := uint32(0), uint32(0), uint32(0), uint32(0)
	count := 3 * Max(RC5_KEY, RC5_SUB)
	for k := 0; k < count; k++ {
		c.mSub[i] = rotl(uint32(c.mSub[i]+x+y), 3)
		x = c.mSub[i]
		i = (i + 1) % RC5_SUB
		c.mKey[j] = rotl((c.mKey[j] + x + y), x+y)
		y = c.mKey[j]
		j = (j + 1) % RC5_KEY

	return c, nil

func (rc *RC5) Decrypt(buf *[]byte, length int) {
	leng := length / 8

	for k := 0; k < leng; k++ {
		lv := uint32(buf[2*k])
		rv := uint32(buf[2*k+1])
		for i := RC5_12; i >= 1; i-- {
			rv = rotr((rv - rc.mSub[2*i+1]), lv) ^ lv
			lv = rotr((lv - rc.mSub[2*i]), rv) ^ rv

		buf[2*k] = byte(lv - rc.mSub[0])
		buf[2*k+1] = byte(rv - rc.mSub[1])


func rotl(aValue uint32, aCount uint32) uint32 {
	leftShift := uint32(aCount % 32)
	rightShift := 32 - leftShift

	return (aValue << leftShift) | (aValue >> rightShift)

func rotr(aValue uint32, aCount uint32) uint32 {
	rightShift := uint32(aCount % 32)
	leftShift := 32 - rightShift

	return (aValue >> rightShift) | (aValue << leftShift)

func Min(x, y int) int {
	if x < y {
		return x
	return y

func Max(x, y int) int {
	if x > y {
		return x
	return y


Edited by W1cked

Share this post

Link to post
Share on other sites

It looks like this line of your seed generator may be wrong.

c.mKey[z] = uint32(seed[z])

Should probably be:

c.mKey[z] = uint32(seed[z * 4])

Here's another reference from one of my C# projects, if it helps:

Share this post

Link to post
Share on other sites
6 hours ago, W1cked said:

Using your Comet source I was able to get the Decrypt up and running! Thank you.

Question about the Encrypt though. It appears that L112 will throw an OutofRange exception.

Is there a reason why dst is made into a new byte array an eight of the size of the src array?

You are correct. I don't think I reference that function, but feel free to log a bug against it and I'll fix it once I return home (I'll be out for another few days). Thanks!

  • Like 1

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


Important Information

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