fix: refactor RSA bits to remove unneeded classes (#733)
And flagged members to ensure they are not exposed publicly
diff --git a/googleapis_auth/CHANGELOG.md b/googleapis_auth/CHANGELOG.md
index 06fcb3f..7a08889 100644
--- a/googleapis_auth/CHANGELOG.md
+++ b/googleapis_auth/CHANGELOG.md
@@ -1,3 +1,5 @@
+## 2.2.1-wip
+
## 2.2.0
- Added `quotaProject` support to existing credentials classes
diff --git a/googleapis_auth/lib/src/crypto/asn1.dart b/googleapis_auth/lib/src/crypto/asn1.dart
index 04d7892..6169a3e 100644
--- a/googleapis_auth/lib/src/crypto/asn1.dart
+++ b/googleapis_auth/lib/src/crypto/asn1.dart
@@ -8,7 +8,7 @@
import 'package:meta/meta.dart';
-import 'rsa.dart';
+import 'rsa.dart' as rsa;
// ignore: avoid_classes_with_only_static_members
abstract final class ASN1Parser {
@@ -91,7 +91,7 @@
switch (tag) {
case integerTag:
final size = readEncodedLength();
- return ASN1Integer._(RSAAlgorithm.bytes2BigInt(readBytes(size)));
+ return ASN1Integer._(rsa.bytes2BigInt(readBytes(size)));
case octetStringTag:
final size = readEncodedLength();
return ASN1OctetString._(readBytes(size));
diff --git a/googleapis_auth/lib/src/crypto/rsa.dart b/googleapis_auth/lib/src/crypto/rsa.dart
index 571a010..160f920 100644
--- a/googleapis_auth/lib/src/crypto/rsa.dart
+++ b/googleapis_auth/lib/src/crypto/rsa.dart
@@ -9,6 +9,8 @@
import 'dart:typed_data';
+import 'package:meta/meta.dart';
+
/// Represents integers obtained while creating a Public/Private key pair.
final class RSAPrivateKey {
/// First prime number.
@@ -50,57 +52,52 @@
);
}
-/// Provides a [rawSign] method for signing messages with a [RSAPrivateKey].
-// ignore: avoid_classes_with_only_static_members
-abstract final class RSAAlgorithm {
- /// Performs the private key operation (signing) on [bytes] with the private
- /// [key].
- ///
- /// Others who have access to the public key will be able to verify this
- /// the result.
- ///
- /// The [intendedLength] argument specifies the number of bytes in which the
- /// result should be encoded. Zero bytes will be used for padding.
- static Uint8List rawSign(
- RSAPrivateKey key,
- List<int> bytes,
- int intendedLength,
- ) {
- final message = bytes2BigInt(bytes);
- final encryptedMessage = _encryptInteger(key, message);
- return integer2Bytes(encryptedMessage, intendedLength);
- }
+/// Performs the private key operation (signing) on [bytes] with the private
+/// [key].
+///
+/// Others who have access to the public key will be able to verify this
+/// the result.
+///
+/// The [intendedLength] argument specifies the number of bytes in which the
+/// result should be encoded. Zero bytes will be used for padding.
+@internal
+Uint8List rawSign(RSAPrivateKey key, List<int> bytes, int intendedLength) {
+ final message = bytes2BigInt(bytes);
+ final encryptedMessage = _encryptInteger(key, message);
+ return integer2Bytes(encryptedMessage, intendedLength);
+}
- static BigInt _encryptInteger(RSAPrivateKey key, BigInt x) {
- // The following is equivalent to `(x % key.n).modPow(key.d, key.n)` but is
- // much more efficient. It exploits the fact that we have dmp1/dmq1.
- var xp = (x % key.p).modPow(key.dmp1, key.p);
- final xq = (x % key.q).modPow(key.dmq1, key.q);
- while (xp < xq) {
- xp += key.p;
- }
- return ((((xp - xq) * key.coeff) % key.p) * key.q) + xq;
+BigInt _encryptInteger(RSAPrivateKey key, BigInt x) {
+ // The following is equivalent to `(x % key.n).modPow(key.d, key.n)` but is
+ // much more efficient. It exploits the fact that we have dmp1/dmq1.
+ var xp = (x % key.p).modPow(key.dmp1, key.p);
+ final xq = (x % key.q).modPow(key.dmq1, key.q);
+ while (xp < xq) {
+ xp += key.p;
}
+ return ((((xp - xq) * key.coeff) % key.p) * key.q) + xq;
+}
- static BigInt bytes2BigInt(List<int> bytes) {
- var number = BigInt.zero;
- for (var i = 0; i < bytes.length; i++) {
- number = (number << 8) | BigInt.from(bytes[i]);
- }
- return number;
+@internal
+BigInt bytes2BigInt(List<int> bytes) {
+ var number = BigInt.zero;
+ for (var i = 0; i < bytes.length; i++) {
+ number = (number << 8) | BigInt.from(bytes[i]);
}
+ return number;
+}
- static Uint8List integer2Bytes(BigInt integer, int intendedLength) {
- if (integer < BigInt.one) {
- throw ArgumentError('Only positive integers are supported.');
- }
- final bytes = Uint8List(intendedLength);
- for (var i = bytes.length - 1; i >= 0; i--) {
- bytes[i] = (integer & _bigIntFF).toInt();
- integer >>= 8;
- }
- return bytes;
+@visibleForTesting
+Uint8List integer2Bytes(BigInt integer, int intendedLength) {
+ if (integer < BigInt.one) {
+ throw ArgumentError('Only positive integers are supported.');
}
+ final bytes = Uint8List(intendedLength);
+ for (var i = bytes.length - 1; i >= 0; i--) {
+ bytes[i] = (integer & _bigIntFF).toInt();
+ integer >>= 8;
+ }
+ return bytes;
}
final _bigIntFF = BigInt.from(0xff);
diff --git a/googleapis_auth/lib/src/crypto/rsa_sign.dart b/googleapis_auth/lib/src/crypto/rsa_sign.dart
index dc2654c..77ca54c 100644
--- a/googleapis_auth/lib/src/crypto/rsa_sign.dart
+++ b/googleapis_auth/lib/src/crypto/rsa_sign.dart
@@ -7,13 +7,15 @@
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
+import 'package:meta/meta.dart';
-import 'rsa.dart';
+import 'rsa.dart' as rsa;
/// Used for signing messages with a private RSA key.
///
/// The implemented algorithm can be seen in
/// RFC 3447, Section 9.2 EMSA-PKCS1-v1_5.
+@internal
final class RS256Signer {
// DigestInfo :== SEQUENCE {
// digestAlgorithm AlgorithmIdentifier,
@@ -53,7 +55,7 @@
0x20,
];
- final RSAPrivateKey _rsaKey;
+ final rsa.RSAPrivateKey _rsaKey;
RS256Signer(this._rsaKey);
@@ -74,6 +76,6 @@
offset += _rsaSha256DigestInfoPrefix.length;
block.setAll(offset, digest);
- return RSAAlgorithm.rawSign(_rsaKey, block, modulusLen);
+ return rsa.rawSign(_rsaKey, block, modulusLen);
}
}
diff --git a/googleapis_auth/pubspec.yaml b/googleapis_auth/pubspec.yaml
index aa9dd4a..dc29e5c 100644
--- a/googleapis_auth/pubspec.yaml
+++ b/googleapis_auth/pubspec.yaml
@@ -1,5 +1,5 @@
name: googleapis_auth
-version: 2.2.0
+version: 2.2.1-wip
description: Obtain Access credentials for Google services using OAuth 2.0
repository: https://github.com/google/googleapis.dart/tree/master/googleapis_auth
diff --git a/googleapis_auth/test/crypto/rsa_test.dart b/googleapis_auth/test/crypto/rsa_test.dart
index 7c0df2f..76916cb 100644
--- a/googleapis_auth/test/crypto/rsa_test.dart
+++ b/googleapis_auth/test/crypto/rsa_test.dart
@@ -4,7 +4,7 @@
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
-import 'package:googleapis_auth/src/crypto/rsa.dart';
+import 'package:googleapis_auth/src/crypto/rsa.dart' as rsa;
import 'package:test/test.dart';
import '../test_utils.dart';
@@ -14,19 +14,9 @@
void main() {
test('integer2Bytes converts BigInt to byte list', () {
- expect(RSAAlgorithm.integer2Bytes(BigInt.one, 1), [1]);
- expect(RSAAlgorithm.integer2Bytes(_bigNumber, 9), [
- 2,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- ]);
- expect(RSAAlgorithm.integer2Bytes(_bigNumber, 12), [
+ expect(rsa.integer2Bytes(BigInt.one, 1), [1]);
+ expect(rsa.integer2Bytes(_bigNumber, 9), [2, 0, 0, 0, 0, 0, 0, 0, 0]);
+ expect(rsa.integer2Bytes(_bigNumber, 12), [
0,
0,
0,
@@ -40,15 +30,12 @@
0,
0,
]);
- expect(
- () => RSAAlgorithm.integer2Bytes(BigInt.zero, 1),
- throwsArgumentError,
- );
+ expect(() => rsa.integer2Bytes(BigInt.zero, 1), throwsArgumentError);
});
test('bytes2BigInt converts byte list to BigInt', () {
- expect(RSAAlgorithm.bytes2BigInt([1]), BigInt.one);
- expect(RSAAlgorithm.bytes2BigInt([2, 0, 0, 0, 0, 0, 0, 0, 0]), _bigNumber);
+ expect(rsa.bytes2BigInt([1]), BigInt.one);
+ expect(rsa.bytes2BigInt([2, 0, 0, 0, 0, 0, 0, 0, 0]), _bigNumber);
});
test('rawSign performs raw RSA signing', () {
@@ -72,7 +59,7 @@
26, 217, 230, 133, 217, 76,
];
expect(
- RSAAlgorithm.rawSign(testPrivateKey, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 256),
+ rsa.rawSign(testPrivateKey, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 256),
encryptedData,
);
});