This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
KingofGamesYami's profile picture

[Challenge] How Secure is my code generator?

Started by KingofGamesYami, 30 September 2014 - 07:29 PM
KingofGamesYami #1
Posted 30 September 2014 - 09:29 PM
I created a rolling-code generator myself, using my knowledge of math & the concept
Here's the three codes I generated using it, if you can break it please let me know. I'm fairly confident in my code though.

kdKaDTdWE3amPT0gNhqKiwkfxwojVXWCUyuIIIfblYcBhxE0voWZdKjJ1CBffrujWX9EdXR3NX4XtZd0zUw9xAdIZkjfdX9at32yQZkuZA8CnTERBT2weAXRhY9TdcF+2ivbYVfJaMIjWUOcgQTfUGKtWyDIr8WxW2Yq4c/dXl1cxbKCEZSUS6lyZVKyJbUIvrw7honMuAbXaVhfQUQWytFfZKF5N9fYSJxbUEmATp9hoQ8dfNYxgZ+sOZTGLk9A3ddcSQwUzCMu2VgjAZNZnUQLTppDVXaHkVydkC24ZcZtdUqRa2PMmAgLXEx4scI2biqtx5y1up6VtngCF5BAqg==
AAAABhswCQAAaWkQsQ0AAAR4AFARMAAAMBUAEAAAAAAAAAgaAAAAAAAAABCAAAAAIAAiAAAAGgA4AAAAAChpALckACQAAADgAAAAiABxQAcBABgIp2kAAKcAAAAwAAAAABUAgDAAAAARICIAAAIAgEAAYBAAAAAAYAAVAAAAIEDgAAAACAAA2AAAAJAAqAAEAAAdAAAAADAAgMCAiCKwAACAQAAAGwAAJABggMgAcACAAAdoAAAYAAAASQAAcfggAADgyGCgABFxAMARAAAgACLXcAAiMAAAAOAAAOgAAAAAAFAAgIAAAATX4CgAAACxABUAAAAAAAAAAAABOAAgAA==
AAAAMFiBBAAAgIAIAAYAAAIAAIAIgQAAgQoACAAAAAAAAAQNAAAAAAAAAAgAAAAAEAARAAAADQDBAAAAAEGAAAASABIAAAAAAAAAAAAAILcAAMAEAIAAAAAAAACBAAAAAAoAAIEAAAAIEBEAAAEAACAAAAgAAAAAAAAKAAAAECAAAAAABAAAAAAAAAAAAAACAABoAAAAAIEAAAAAABEAAAAAIAAAWAAAEgAAAAAAAAAAALcAAADAAAAAyAAAAAAQAAAAAAAAAAgAAAAIAAAQABEAAAARgQAAAAAAAAAAAAAAAIAAAAAAAAIAAEEAAAAAAAoAAAAAAAAAAAAAwQAQAA==
oeed #2
Posted 01 October 2014 - 01:23 AM
Honestly, I wouldn't know where to begin. Could you maybe explain a little about it? From brief research it looks like it's the same 'key' but the hash/whatever it's called is always different, which is useful for car keys.
sci4me #3
Posted 01 October 2014 - 02:50 AM
This question is *impossible* to answer… there isn't NEARLY enough information! What exactly is this?
KingofGamesYami #4
Posted 01 October 2014 - 04:18 AM
I start with a base key, then generate a "next key" in the series, as oeed stated. The base key is generated by this function:

function genCode()
  local code = ""
  for i = 1, 256 do --#i might've actually used a different number here on those, I've been messing with it
   code = code .. string.char( math.random( 0, 225 ) )
   sleep( 0 )
  end
  return code
end

Also, I run the results through a base64 encrypter so a) I can read it and B)/> events work properly.

I got the idea after watching an episode of Numb3rs, in which they tracked the criminal's car by matching the algorithm. I wanted to make something similar, thus this code. If you want, I can provide more of the "next" sequences.
Edited on 01 October 2014 - 02:19 AM
theoriginalbit #5
Posted 01 October 2014 - 06:10 AM
what is the use case of this? hashing, encrypting, what?
Bomb Bloke #6
Posted 01 October 2014 - 07:59 AM
Encryption. The idea is that even if you figure out the key used to encrypt one message (along with the algorithm used to apply it), you won't automatically know the key of subsequent messages (as there's another algorithm producing new keys each time one is sent).

If done correctly, this should be quite difficult to break even if the full source is available.
KingofGamesYami #7
Posted 01 October 2014 - 04:54 PM
Update: I didn't like all the "A"s being spit out so I tweaked my code. Here's the new results (there's 10 of them):

WrID2E+Plak=
4M2XVPjoq3E=
3E/uMMtzvY8=
FvitgfPCkOg=
sMsKQLplCXM=
fvNQyBNxCcI=
6rrJbSiPCWU=
2xOaLbHoCXE=
5ShV6KZzCY8=
2LEwcwHCCeg=
Anavrins #8
Posted 01 October 2014 - 05:57 PM
I'd say it's as secure as math.random is, which is "enough".
It's not cryptographically secure, but it's enough for most non-crypto uses.
KingofGamesYami #9
Posted 01 October 2014 - 06:22 PM
I'd say it's as secure as math.random is, which is "enough".
It's not cryptographically secure, but it's enough for most non-crypto uses.

How do you arrive at that conclusion? I only use math.random for the original string, not the modifications afterward.
oeed #10
Posted 02 October 2014 - 01:37 AM
I'd say it's as secure as math.random is, which is "enough".
It's not cryptographically secure, but it's enough for most non-crypto uses.

The problem with using math.random, is well, it's random. It basically means that the result could be anything, making it pretty much pointless.
KingofGamesYami #11
Posted 02 October 2014 - 02:19 AM
Well, since nobody has figured this out yet, here's the code!

function genCode()
  local code = ""
  for i = 1, 256 do
    code = code .. string.char( math.random( 0, 225 ) )
    sleep( 0 )
  end
  return code
end

function next( code, aop, bop )
  local new = ""
  for char in code:gmatch( "." ) do
    local old = char:byte()
    local a = math.floor( old^ aop / bop ) % 255
    local b = math.floor( old^ bop / aop ) % 255
    if a > b then
      new = new .. string.char( a )
    else
      new = new .. string.char( b )
    end
  end
  return new
end

I was calling the next() function using 9 for the aop and 2 for the bop.
Bomb Bloke #12
Posted 02 October 2014 - 02:56 AM
The problem with using math.random, is well, it's random. It basically means that the result could be anything, making it pretty much pointless.

The whole idea is that the key "could be anything". You're not supposed to be able to work out what the key is.

Let's examine a basic use-case:

Say you've got two computers, communicating by wireless rednet. One asks for a password, the other opens a door. Both are secure from tampering (eg rebooting, pickaxing etc) by way of warded blocks.

Problem: Sending the "open the door" command from one to the other results in a signal that can be eavesdropped on. Someone can record it, and re-send it themselves whenever they want to open the door.

What about if you encrypt the signal? That, on its own, is still useless: You're still sending the same "open the door" command each time (even if it is encrypted), and so even if people can't understand the signal, they can still record and replay it.

So that's where this sort of system comes into play. Every time the signal is sent, the encryption key is run through an algorithm that alters it - any given transmission only works once. To break it, you need to record a signal, work out the key in order to decrypt it, generate a new key and re-encrypt the signal using that.

Assuming you've got full source code access, the way to break this system (that is, get yourself to the point where you could predict the next code in the sequence) would be to generate base keys enmass until you find the right one. There are only ~60k possibilities, so I don't think it'd take all that long. This could be made dramatically more difficult by not showing us the first however many consecutive codes, but instead starting from a few iterations in.

Without full source access… Well, good luck. :P/>

Well, since nobody has figured this out yet, here's the code!

Did you perform any encryption using those generated codes before the base64 conversion, or…?
Edited on 02 October 2014 - 12:56 AM
oeed #13
Posted 02 October 2014 - 03:06 AM
The problem with using math.random, is well, it's random. It basically means that the result could be anything, making it pretty much pointless.

The whole idea is that the key "could be anything". You're not supposed to be able to work out what the key is.

Maybe I could've worded it better, but if it "could be anything" wouldn't it would be impossible for the 'door' to know whether it was a valid key? I mean, couldn't you just hit n amount of characters on your keyboard and send that? How do you actually work out from the door side whether it's valid?
Edited on 02 October 2014 - 01:07 AM
KingofGamesYami #14
Posted 02 October 2014 - 03:36 AM
-snip long post-
Did you perform any encryption using those generated codes before the base64 conversion, or…?
1 - Generate random 8 digit string
2 - run through code generator, capturing the next 9 "sets"
3 - use base64 on all the codes
4 - save to file so I can copy/paste to the forum

If this doesn't answer your question, please specify what you are looking for.
Bomb Bloke #15
Posted 02 October 2014 - 04:08 AM
Maybe I could've worded it better, but if it "could be anything" wouldn't it would be impossible for the 'door' to know whether it was a valid key? I mean, couldn't you just hit n amount of characters on your keyboard and send that? How do you actually work out from the door side whether it's valid?

By giving the door-side a copy of the original randomly generated key. Both sides then proceed to generate new keys not randomly, but by altering the original key.

In short, it doesn't much matter how the original key is created, so long as it can't be guessed. As it turns out, though, KoGY is showing us his keys - as opposed to codes encrypted using those keys - so it should be pretty easy to break, source in hand.

If this doesn't answer your question, please specify what you are looking for.

That's what I'm after. I'll have a bit of a play with it.
Bomb Bloke #16
Posted 02 October 2014 - 04:31 AM
The code that comes after 2LEwcwHCCeg= is VKaBwgBlCXM=.

I'll see if I can come up with something that solves aop/bop.

Edit:

Here we go, give it any two consecutive codes from a sequence and it should be able to produce the next ten.

Spoiler
code1 = "2LEwcwHCCeg="
code2 = "VKaBwgBlCXM="

-----KoGY's code:
function genCode()
  local code = ""
  for i = 1, 8 do
    code = code .. string.char( math.random( 0, 225 ) )

  end
  return code
end

function next( code, aop, bop )
  local new = ""
  for char in code:gmatch( "." ) do
    local old = char:byte()
    local a = math.floor( old^ aop / bop ) % 255
    local b = math.floor( old^ bop / aop ) % 255
    if a > b then
      new = new .. string.char( a )
    else
      new = new .. string.char( b )
    end
  end
  return new
end
-----End KoGY's code

-----Base64 code pulled from some website:
-- character table string
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

-- encoding
function enc(data)
    return ((data:gsub('.', function(x) 
        local r,b='',x:byte()
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
        return r;
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
        if (#x < 6) then return '' end
        local c=0
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
        return b:sub(c+1,c+1)
    end)..({ '', '==', '=' })[#data%3+1])
end

-- decoding
function dec(data)
    data = string.gsub(data, '[^'..b..'=]', '')
    return (data:gsub('.', function(x)
        if (x == '=') then return '' end
        local r,f='',(b:find(x)-1)
        for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
        return r;
    end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
        if (#x ~= 8) then return '' end
        local c=0
        for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
        return string.char(c)
    end))
end
---------End base64 code

--------aop/bop brute forcing code:
print(code1)
print(code2)

code1, code2 = dec(code1), dec(code2)

aop, bop = 1,1

flip = false

for i=1,#code1 do
    while true do
        curChar = next(code1:sub(i,i),flip and aop or bop,flip and bop or aop)
        if curChar == code2:sub(i,i) then
            break
        else
            aop = aop + 1
            if aop > bop then
                aop = 1
                bop = bop + 1
                flip = not flip
            end
        end
    end
end

print("aop: "..aop.." bop: "..bop)

for i=1,10 do
    code2 = next(code2,aop,bop)
    print(enc(code2))
end

Again, if the codes were actually used to encrypt something, and only the encrypted results were visible, this'd be much more secure. As it stands, if the source is hidden, then someone professionally experienced in breaking codes shouldn't have too much trouble; but I doubt you'd ever find someone like that one these boards (let alone on a MineCraft server).

Ideally, however, the generator should be secure regardless as to whether people can read its code.
Edited on 02 October 2014 - 05:48 AM