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

Request info on bytecode limitation #91

Closed
4 tasks done
jeremyben opened this issue Jan 25, 2023 · 7 comments
Closed
4 tasks done

Request info on bytecode limitation #91

jeremyben opened this issue Jan 25, 2023 · 7 comments
Labels
enhancement New feature or request

Comments

@jeremyben
Copy link

jeremyben commented Jan 25, 2023

You mention here that string contents are not protected in V8 bytecode:
https://evite.netlify.app/guide/source-code-protection.html#limitations-of-v8-bytecode

I was wondering if we could build a string from a buffer like so:

const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72])
const str = buf.toString()

And the string would then be protected ?

Validations

@jeremyben jeremyben added the enhancement New feature or request label Jan 25, 2023
@alex8088
Copy link
Owner

@jeremyben Thanks! This sounds like a feasible solution 🤔 . I have a similar idea( repacing string via function or buffer). But this still needs some validation experiments. I will try. Your idea is very constructive.

@jeremyben
Copy link
Author

jeremyben commented Jan 25, 2023

It seems this works.
I made a test with the encryptionKey option of electron-store.

  • I tried storing the key as plain string, built the app, and I could see my key in the jsc file next to encryptionKey.
  • Then I tried storing the key built manually from a buffer, and in the jsc file I could only see encryptionKey in plain sight.

🙂

@jeremyben
Copy link
Author

jeremyben commented Jan 26, 2023

Hey I figured out a way to do it automatically with a dedicated tag.

I use a tagged template that is a noop for development, but that is replaced at build time.
(This is a well-known technique: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#raw_strings)

export const __protect = (str: readonly string[], ...values: never[]) => String.raw({ raw: str })

// use it like so:
const key = __protect`secret_stuff`

Since we only want to transform string constants, we forbid any interpolation thanks to never[].

Then I added a vite transform plugin to my configuration to replace the tagged strings with the buffer technique:

/**
 * @returns {import('vite').Plugin}
 */
function protectStringsInBytecode() {
	const filter = vite.createFilter(/\.(m?[jt]s|[jt]sx)$/)

	return {
		name: 'protectString',
		apply: 'build',
		transform(code, id) {
			if (!filter(id)) return

			const replaced = code.replace(/__protect`(.+)`/gim, (_, str) => {
				const { data } = Buffer.from(str).toJSON()
				return `Buffer.from([${data.join(',')}]).toString()`
			})

			return replaced
		},
	}
}

I think it could be added to your bytecode plugin as an option rather than a independant plugin.

@alex8088
Copy link
Owner

@jeremyben That's great. Thank you for taking the time to study this problem. I'll try again later.

@alex8088
Copy link
Owner

@jeremyben

Be inspired by you!

I found a better solution. Bytecode does not protect strings but numbers, so we can convert string to char code. The String.fromCharCode static method is great for this. For example:

const encryptKey = 'ABC'

⬇️

const encryptKey = String.fromCharCode(65, 66, 67)

This conversion method is very simple and does not require additional processing by developers.

I will add an option(protectedStirngs) to the bytecode plugin to specify the strings to be protected. The plugin will convert the specified string to char code and replace it when building.

@jeremyben
Copy link
Author

jeremyben commented Jan 30, 2023

Yes that's simpler, maybe less runtime overhead but I can't say about that part.

What would your api look like ?
I need to protect a lot of different strings (sensitive shell commands), and I can't list them all in the vite config.
If you want to avoid the tagging function, maybe allow regex ?

Be aware I also discovered that you should probably apply the escape sequences at build time the way the javascript engine does it, for example with windows paths (C:\\path\\to\\file).
Try it for yourself and if you encounter the same problem, use this package: https://www.npmjs.com/package/unraw

@alex8088
Copy link
Owner

alex8088 commented Feb 7, 2023

New ver 1.0.19 is out! Support for protecting strings in v8 bytecode. But regular expression matching strings are not yet supported. Anyway, thank you @jeremyben .

more details: https://evite.netlify.app/guide/source-code-protection.html#limitations-of-v8-bytecode

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

No branches or pull requests

2 participants