Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generating invalid ShortUUIDs #64

Closed
kevinkirkup opened this issue Dec 10, 2021 · 14 comments
Closed

Generating invalid ShortUUIDs #64

kevinkirkup opened this issue Dec 10, 2021 · 14 comments

Comments

@kevinkirkup
Copy link

kevinkirkup commented Dec 10, 2021

I'm calling shortuuid.uuid() in our unit test which run regularly and I'm seeing it generate some invalid UUIDs

Such as 5vHqLc9etTWW3AVrEJvBez.

The library seems to think this is a valid UUID

>>> shortuuid.decode("5vHqLc9etTWW3AVrEJvBez")
UUID('160427e7-f28e-40ee-9f7a-d473721488c8')

But your website does not:
https://shortuuid.com/

I'm also validating this with some Elixir libraries and they are reporting that it's invalid as well.

Any help would be greatly appreciated.

@skorokithakis
Copy link
Owner

Ah, that website is unrelated to the library. I'm not sure why the site says they're invalid, but they look like valid UUIDs to me? Are you aware of anything that'd make them invalid?

@kevinkirkup
Copy link
Author

kevinkirkup commented Dec 10, 2021

It looked like the decoded value was 33 instead of 32 characters in length.

I can check another library to see if they are seeing it as well.

@skorokithakis
Copy link
Owner

Hmm, and this was generated by .uuid()?

@kevinkirkup
Copy link
Author

Yes.

@skorokithakis
Copy link
Owner

That's very odd, that'd mean that either Python generates invalid UUIDs, or we're encoding them wrong...

@kevinkirkup
Copy link
Author

Let me see if I can validate it against the nodejs package to see what it thinks. It could be An issue with the Elixir package.

@kevinkirkup
Copy link
Author

kevinkirkup commented Dec 13, 2021

OK, so I was able to use this golang library to test:
https://github.com/lithammer/shortuuid

Here is the test code:

package shortuuid

import (
	"testing"

	"github.com/google/uuid"
)

var testVector = []struct {
	uuid      string
	shortuuid string
}{
	{"160427e7-f28e-40ee-9f7a-d473721488c8", "5vHqLc9etTWW3AVrEJvBez"},
}

func TestDecoding(t *testing.T) {
	for _, test := range testVector {
		u1, err := uuid.Parse(test.uuid)
		if err != nil {
			t.Error(err)
		}

		u2, err := DefaultEncoder.Decode(test.shortuuid)
		if err != nil {
			t.Error(err)
		}

		if u1 != u2 {
			t.Errorf("expected %q, got %q", u1, u2)
		}
	}
}

Here is what it's returning:

❯ go test
--- FAIL: TestDecoding (0.00s)
    shortuuid_test.go:25: UUID length overflow for "5vHqLc9etTWW3AVrEJvBez"
    shortuuid_test.go:29: expected "160427e7-f28e-40ee-9f7a-d473721488c8", got "00000000-0000-0000-0000-000000000000"
FAIL
exit status 1
FAIL	github.com/lithammer/shortuuid/v3	0.105s

UUID length overflow This is the same issue that I was seeing with the Elixir Library.

@skorokithakis
Copy link
Owner

Hmm, I'm mystified. The UUID seems valid to me. Which part did you say had 33 characters? The one in your comment has 32:

In [14]: len("160427e7-f28e-40ee-9f7a-d473721488c8".replace("-", ""))
Out[14]: 32

@kevinkirkup
Copy link
Author

Test.decode("5vHqLc9etTWW3AVrEJvBez")
💧 ❯ 7. "13E5029F9ECECDC0FE6290538B66F4D78"

@skorokithakis
Copy link
Owner

Oh, it looks like all these libraries use the "legacy" decoding mode. This was changed in #35 because putting the LSB first had some issues. Unfortunately, this means that all these sites/libraries are only compatible with the legacy ShortUUID decoding, and not the new MSB-first mode:

In [25]: shortuuid.decode("zeBvJErVA3WWTte9cLqHv5", legacy=True)
Out[25]: UUID('160427e7-f28e-40ee-9f7a-d473721488c8')

@kevinkirkup
Copy link
Author

This is what I'm seeing:

>>> shortuuid.decode("5vHqLc9etTWW3AVrEJvBez", legacy=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/kevinkirkup/anaconda3/envs/atlantis/lib/python3.8/site-packages/shortuuid/main.py", line 79, in decode
    return _uu.UUID(int=string_to_int(string, self._alphabet))
  File "/Users/kevinkirkup/anaconda3/envs/atlantis/lib/python3.8/uuid.py", line 205, in __init__
    raise ValueError('int is out of range (need a 128-bit value)')
ValueError: int is out of range (need a 128-bit value)

So that makes sense. Is there a way that I can generate a shortuuid in legacy mode?

@skorokithakis
Copy link
Owner

Sure, all you need to do is reverse the string really, but why would you want that?:

shortuuid.uuid()[::-1]

@kevinkirkup
Copy link
Author

I'm using this library to generate shortuuid's to validate my OpenAPI Spec for my Elixir server and, as you mention above, it is only compatible with the legacy encoding, so I'm kinda stuck with it.

Thanks for your help!

@skorokithakis
Copy link
Owner

Ahh okay. Yeah, reversing the string should work fine, that's all we do internally anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants