-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Support conversion between BigInt and binary representation #32803
Comments
Little endian is efficient for many CPUs, intel and (most) ARM at least, whereas big endian is "network byte order", so often used in communications. Either makes sense, either has advantages. I would prefer a way to write big integers into a |
As a reference, Java's BigInteger class has a default constructor that takes a big-endian byte array and a The BigInteger class from the bignum package also works like that. I'm currently migrating the Pointy Castle code to BigInt and we also quite heavily rely on that functionality. |
@lrhn I think that adding it to dart:typed_data like a normal fixed size integer wouldn't work, as BigInt is almost certainly implemented in a variable size. So, if I needed to copy a bigint into a uint8list, I wouldn't have a good way of knowing how big to make the initial buffer. |
@lrhn Also, since BigInt is in core, it needs to return |
Core methods can return typed data lists, and be typed as such, we just try to avoid it if it isn't necessary. I'd probably prefer adding |
@lrhn What is the roadmap for this? I agree that for efficient serialization etc, a method in |
Any update on this?? |
We are very busy doing the already planned Dart 2 features, so I don't think it's likely that a feature like this will make it into Dart 2.0. (It's kind-of trivial once the design is nailed down, but so are most of the other things we are currently doing). For now, I'll recommend just using helper functions like: BigInt readBytes(Uint8List bytes) {
BigInt read(int start, int end) {
if (end - start <= 4) {
int result = 0;
for (int i = end - 1; i >= start; i--) {
result = result * 256 + bytes[i];
}
return new BigInt.from(result);
}
int mid = start + ((end - start) >> 1);
var result = read(start, mid) + read(mid, end) * (BigInt.one << ((mid - start) * 8));
return result;
}
return read(0, bytes.length);
}
Uint8List writeBigInt(BigInt number) {
// Not handling negative numbers. Decide how you want to do that.
int bytes = (number.bitLength + 7) >> 3;
var b256 = new BigInt.from(256);
var result = new Uint8List(bytes);
for (int i = 0; i < bytes; i++) {
result[i] = number.remainder(b256).toInt();
number = number >> 8;
}
return result;
} (There are lots of opportunities for optimizations, obviously). |
(You made a typo on that long line.) Yeah that was my alternative, but I was kinda trying to avoid that. But yeah since it won't land 2.0, I'll probably do this instead. |
Does anyone know of any method to convert uin8list to core.BigInt? How have you corrected the typo? Solution on https://github.com/stevenroose/dart-cryptoutils/pull/5/files works for me (changing some data type) but I don't know if is the correct solution. I want a method like Java BigInteger. |
Typo has been corrected (line was truncated when cut-n-pasted from a console). |
Not sure if this belongs here but I found it helpful; the authors of PointyCastle include a utility to do the conversion: https://github.com/PointyCastle/pointycastle/blob/master/lib/src/utils.dart (actually @stevenroose made that change). If you are using PointyCastle anyway I think that is a good alternative. |
Any update on this? |
@lrhn – could we add a constructor on |
What is expected of the 'byte view' of negative BigInt values? We also need to consider if the operations can be implemented efficiently for JavaScript BigInt values, since we will eventually want to use JavaScript BigInt when compiling for the browser. Tree-structured algorithms like |
@stevenroose How are the requested APIs used? i.e. why are they useful? Is there a standard that requires the format? |
We now plan to seal typed_data classes (#45115), which also opens up the ability to add members on the classes without breaking anyone. That makes it more likely that we'll actually be able to add a For that reason, a |
@lrhn Should That would preserve a path for |
I think it would be a good idea to seal Effectively, we've already assumed that it is sealed because we start all the instance methods with It'd be a different request, though. I'd vote for it. |
A direct port from bouncy-castle to add SRP support to pointy-castle. For details on the protocol visit https://en.wikipedia.org/wiki/Secure_Remote_Password_protocol There is code duplication in encode/decode BigInt due to dart not yet supporting conversion natively. Tracked on dart-lang/sdk#32803 When using the protocol, we use the following parameters to improve security and efficiency, please do your research as the protocol itself will not protect you from mistakes. Digest: "SHA-256" SecureRandom: "AES/CTR/AUTO-SEED-PRNG"; N,g: Generate own big prime(4096) We also recommend using a KDF, such as scrypt to secure the password, hence the verifier.
Figured I would leave this here in case anybody else came across it in the future but I ran into a scenario where I needed this recently here: https://github.com/dropbear-software/todart/blob/main/common/lib/src/types/cloud_resource_identity.dart Here is how I solved it thanks to some help from others in the community Gitter chat /// Converts a [Uint8List] byte buffer into a [BigInt]
static BigInt _convertBytesToBigInt(Uint8List bytes) {
BigInt result = BigInt.zero;
for (final byte in bytes) {
// reading in big-endian, so we essentially concat the new byte to the end
result = (result << 8) | BigInt.from(byte);
}
return result;
} |
@mark-dropbear – make that an extension method and we have 🥇 !!! |
Thanks @kevmoo I will take a look at that later on, have never used extension methods before but I am excited to check them out. By the way, that project I referenced there is most certainly not yet in a state that has a whole lot worth talking about just yet but is heavily inspired by Knarly Vote (There are a few big differences like gRPC rather than cloud functions for example). However, the entire concept is to kind of just use that code base as a playground to explore what fullstack dart could look like and especially while trying to do things the "Google AIP way". I'm intentionally trying to keep the application itself relatively simple (it's just a Todo list kind of app) so that I have something that at least is going to have to bump into "real life problems" but easy enough that I can just focus on the patterns and see where the messy parts are. I was going to ping you when I had something there worth sharing because I figured that both you and a few others might get a kick out of it. |
Hey I was recently working on a project for e2ee for multiple languages and I stumbled upon this problem, I tried @mark-dropbear and @lrhn 's solutions but they were a bit incomplete, the method _convertBytesToBigInt() assumes big-endianness whereas writeBigInt() writes in little-endian so I fixed them. static BigInt readBytes(Uint8List bytes) {
BigInt result = BigInt.zero;
for (final byte in bytes) {
// reading in big-endian, so we essentially concat the new byte to the end
result = (result << 8) | BigInt.from(byte & 0xff);
}
return result;
}
static Uint8List writeBigInt(BigInt number) {
// Not handling negative numbers. Decide how you want to do that.
int bytes = (number.bitLength + 7) >> 3;
var b256 = BigInt.from(256);
var result = Uint8List(bytes);
for (int i = 0; i < bytes; i++) {
result[bytes - 1 - i] = number.remainder(b256).toInt();
number = number >> 8;
}
return result;
} now I'm able to use the same methods for multiple languages without any problems. |
Just like
bignum.BigInteger
supports, please support binary conversion in BigInt as well.More specifically, please provide the following methods:
Possibly, both methods could take a (optional) parameters specifying the endianness, however I think big endian is by far the most common way to represent integers.
The text was updated successfully, but these errors were encountered: