If you find this article helpful to you, welcome to π, my Github.
Recently, when developing this library, WE needed RSA encryption. We searched pub.dev/ and used ENCRYPT
Encrypt RSA only supports OAEP and PKCS1. NoPadding is not supported.
So you need to extend it yourself to support noPadding.
What is RSA padding
There are three commonly used padding modes for RSA encryption: RSA_PKCS1_PADDING, RSA_PKCS1_OAEP_PADDING, and RSA_NO_PADDING.
Like the symmetric encryption algorithms DES and AES, RSA is a block cipher algorithm. It always operates on a block of a fixed length. But unlike AES, block length is related to key Length.
The plaintext length of each RSA encryption is limited by the RSA filling mode, but the block length of each RSA encryption is the key length.
Fill the way | The input | The output |
---|---|---|
RSA_PKCS1_PADDING | Modulus must be at least 11 bytes shorter than RSA_size(RSA) -11 | As long as modulus |
RSA_PKCS1_OAEP_PADDING | RSA_size (rsa) – 41 | As long as modulus |
RSA_NO_PADDING | It can be as long as the RSA key module. If the input plaintext is too long, it must be cut and filled | As long as modulus |
Modulus RSA_NO_PADDING is a complement of 0 when the input data is shorter than the modulus of the key.
The implementation is as follows:
Pubspec.yaml adds dependencies
dependencies:
# encrypt
encrypt: ^ 4.0.0
pointycastle: ^ 1.0.2
Copy the code
encrypt_ext.dart
import 'dart:typed_data';
import 'package:encrypt/encrypt.dart';
import 'package:pointycastle/export.dart' hide Algorithm;
class NoPaddingEncoding extends PKCS1Encoding {
NoPaddingEncoding(this._engine) : super(_engine);
final AsymmetricBlockCipher _engine;
int _keyLength;
bool _forEncryption;
@override
void init(bool forEncryption, CipherParameters params) {
super.init(forEncryption, params);
this._forEncryption = forEncryption;
if (params is AsymmetricKeyParameter<RSAAsymmetricKey>) {
this._keyLength = (params.key.modulus.bitLength + 7) ~ /8; }}int get inputBlockSize {
return _keyLength;
}
int get outputBlockSize {
return _keyLength;
}
@override
int processBlock(
Uint8List inp, int inpOff, int len, Uint8List out, int outOff) {
if (_forEncryption) {
return _encodeBlock(inp, inpOff, len, out, outOff);
} else {
return_decodeBlock(inp, inpOff, len, out, outOff); }}int _encodeBlock(
Uint8List inp, int inpOff, int inpLen, Uint8List out, int outOff) {
if (inpLen > inputBlockSize) {
throw new ArgumentError("Input data too large");
}
var block = new Uint8List(inputBlockSize);
var padLength = (block.length - inpLen);
// θ‘₯0
block.fillRange(0, padLength, 0x00);
block.setRange(padLength, block.length, inp.sublist(inpOff));
return _engine.processBlock(block, 0, block.length, out, outOff);
}
int _decodeBlock(
Uint8List inp, int inpOff, int inpLen, Uint8List out, int outOff) {
var block = new Uint8List(outputBlockSize);
var len = _engine.processBlock(inp, inpOff, inpLen, block, 0);
block = block.sublist(0, len);
if (block.length < outputBlockSize) {
throw new ArgumentError("Block truncated");
}
returnblock.length; }}abstract class AbstractRSAExt {
final RSAPublicKey publicKey;
final RSAPrivateKey privateKey;
final PublicKeyParameter<RSAPublicKey> _publicKeyParams;
final PrivateKeyParameter<RSAPrivateKey> _privateKeyParams;
final AsymmetricBlockCipher _cipher;
AbstractRSAExt({
this.publicKey,
this.privateKey,
}) : this._publicKeyParams = PublicKeyParameter(publicKey),
this._privateKeyParams = PrivateKeyParameter(privateKey),
this._cipher = NoPaddingEncoding(RSAEngine());
}
class RSAExt extends AbstractRSAExt implements Algorithm {
RSAExt({RSAPublicKey publicKey, RSAPrivateKey privateKey})
: super(publicKey: publicKey, privateKey: privateKey);
@override
Encrypted encrypt(Uint8List bytes, {IV iv}) {
if (publicKey == null) {
throw StateError('Can\'t encrypt without a public key, null given.'); } _cipher .. reset() .. init(true, _publicKeyParams);
return Encrypted(_cipher.process(bytes));
}
@override
Uint8List decrypt(Encrypted encrypted, {IV iv}) {
if (privateKey == null) {
throw StateError('Can\'t decrypt without a private key, null given.'); } _cipher .. reset() .. init(false, _privateKeyParams);
return_cipher.process(encrypted.bytes); }}Copy the code
use
final parser = RSAKeyParser();
final encrypter =
Encrypter(RSAExt(publicKey: parser.parse(_publicKey)));
encrypter.doSome...
Copy the code
RSA asymmetric encryption and decryption algorithm Padding