How to set PKCS1 v1.5 padding to RSA in Dart? - flutter

I want to encrypt the value with public key, I used pointycastle package and RSA and PKCS1 v1.5 padding, but this didn't work.
publicKey: 7/ZVKLxKXsQnlVUozywoumbFGbSz8kbH178dT165ODd/a/dUMAsdvs90iCLZo4KVoxZbQpD9d5K/Qgs1wjjylQ==
plainText:
a57b4b30-6b96-11ec-a8cf-c308568a983a
String encrypt(String plaintext, String publicKey) {
var modulusBytes = base64.decode(publicKey);
var modulus = BigInt.parse(hex.encode(modulusBytes), radix: 16);
var exponent = BigInt.parse(hex.encode(base64.decode('AQAB')), radix: 16);
var engine = RSAEngine()
..init(
true,
PublicKeyParameter<RSAPublicKey>(RSAPublicKey(modulus, exponent)),
);
//PKCS1.5 padding
var k = modulusBytes.length;
var plainBytes = utf8.encode(plaintext);
var paddingLength = k - 3 - plainBytes.length;
var eb = Uint8List(paddingLength + 3 + plainBytes.length);
var r = Random.secure();
eb.setRange(paddingLength + 3, eb.length, plainBytes);
eb[0] = 0;
eb[1] = 2;
eb[paddingLength + 2] = 0;
for (int i = 2; i < paddingLength + 2; i++) {
eb[i] = r.nextInt(254) + 1;
}
print(plainBytes.length);
print(eb);
return base64.encode(
engine.process(eb),
);
}

A couple of comments first...
Let's assume that the "public key" you provide is the modulus of an RSA key. We have to assume that the exponent is 65537. You'd normally want to get the public key in a PEM or similar. If that is the modulus, it's painfully short at just 512 bytes.
There only version of PKCS1 that's less than 2.x is 1.5. In particular, pointy castle's implementation in PKCS1Encoding is an implementation of 1.5.
You can only encrypt bytes. So, how are we meant to turn your "plaintext" into bytes. It could be a string that we could just encode in utf8. But it looks like a UUID. Maybe you are meant to interpret it as its normal representation as a 128 bit number, in bytes.
Finally, the output of the encryption will be bytes. How are you meant to send those to the server? Does it want them converted to a string first? If so, how? In base64? In hex?
The following code assumes: yes, that's a 512 bit modulus; the plaintext is not a UUID that can be interpreted, but is just a string that should be converted to ASCII bytes; the output is just an array of bytes.
import 'dart:convert';
import 'dart:typed_data';
import 'package:convert/convert.dart';
import 'package:pointycastle/export.dart';
void main() {
final publicKey =
'7/ZVKLxKXsQnlVUozywoumbFGbSz8kbH178dT165ODd/a/dUMAsdvs90iCLZo4KVoxZbQpD9d5K/Qgs1wjjylQ==';
final plaintext = 'a57b4b30-6b96-11ec-a8cf-c308568a983a';
var modulusBytes = base64.decode(publicKey);
var modulus = BigInt.parse(hex.encode(modulusBytes), radix: 16);
var exponent = BigInt.from(65537);
var engine = PKCS1Encoding(RSAEngine())
..init(
true,
PublicKeyParameter<RSAPublicKey>(RSAPublicKey(modulus, exponent)),
);
print(engine.process(utf8.encode(plaintext) as Uint8List));
}

Related

Convert privateKey to PKCS#8 format in Dart

In FLUTTER - DART using RSA algoritm i get a privateKey. I have this method for encode privateKey to PEM in PKCS#1 format but i need a method for encode the privateKey to PKCS#8 format. I can't finde nothing in internet for that.
Uint8List _encodePrivateKeyToPemPKCS1(RSAPrivateKey privateKey) {
var topLevel = new ASN1Sequence();
var version = ASN1Integer(BigInt.from(0));
var modulus = ASN1Integer(privateKey.n!);
var publicExponent = ASN1Integer(privateKey.exponent!);
var privateExponent = ASN1Integer(privateKey.privateExponent!);
var p = ASN1Integer(privateKey.p!);
var q = ASN1Integer(privateKey.q!);
var dP = privateKey.privateExponent! % (privateKey.p! - BigInt.from(1));
var exp1 = ASN1Integer(dP);
var dQ = privateKey.privateExponent! % (privateKey.q! - BigInt.from(1));
var exp2 = ASN1Integer(dQ);
var iQ = privateKey.q!.modInverse(privateKey.p!);
var co = ASN1Integer(iQ);
topLevel.add(version);
topLevel.add(modulus);
topLevel.add(publicExponent);
topLevel.add(privateExponent);
topLevel.add(p);
topLevel.add(q);
topLevel.add(exp1);
topLevel.add(exp2);
topLevel.add(co);
return topLevel.encodedBytes;
}
This code work for me. Thanks Topaco
https://raw.githubusercontent.com/Ephenodrom/Dart-Basic-Utils/master/lib/src/CryptoUtils.dart
https://raw.githubusercontent.com/Ephenodrom/Dart-Basic-Utils/master/lib/src/StringUtils.dart

I have Modulus and Exponent how to generate JWE for some payload using JavaScript

We have a requirement where we will get modulus from service call to be used for encrypting (JWE) some data at client side
Example of modulus, and exponent (cannot be changed formats)
{
"modulus": "27921539673885756361419156461021876226845445107119091471889357242434620975884246915491757578902818243635599516623468500514580405147004224500529164165175418080296534603814824585285975894063860621755306618118216921360279638839263914961253991832884140339596254323951288609833783395465326689135784495563016459486626252473786100255392919521063720839389818627863002071132030078117996952009416186398741189513852165509082498538217432301912889497439381201450665516807813007876250433333575497298297093128243716605741969339467610040987340399020751603712326128652340270376013354086995479489210853404012768884141354633100389617819",
"exponent": "65537",
}
I am trying to use JavaScript Jose library to generate JWE, but no luck.
I am following below example from internet, but my question is modulus I am using seems to be in biginteger (i guess) format, but the example showing different format.
Is there a better way I can use JOSE for JWE if I have modulus and exponent as shown above? Or can it be done as its shown below, but I am getting an error:
var cryptographer = new Jose.WebCryptographer();
var rsa_key = Jose.Utils.importRsaPublicKey(
{
n:
"c2:4b:af:0f:2d:2b:ad:36:72:a7:91:0f:ee:30:a0:95:d5:3a:46:82:86:96:7e:42:c6:fe:8f:20:97:af:49:f6:48:a3:91:53:ac:2e:e6:ec:9a:9a:e0:0a:fb:1c:db:44:40:5b:8c:fc:d5:1c:cb:b6:9b:60:c0:a8:ac:06:f1:6b:29:5e:2f:7b:09:d9:93:32:da:3f:db:53:9c:2e:ea:3b:41:7f:6b:c9:7b:88:9f:2e:c5:dd:42:1e:7f:8f:04:f6:60:3c:fe:43:6d:32:10:ce:8d:99:cb:76:f7:10:97:05:af:28:1e:39:0f:78:35:50:7b:8e:28:22:a4:7d:11:51:22:d1:0e:ab:6b:6f:96:cb:cf:7d:eb:c6:aa:a2:6a:2e:97:2a:93:af:a5:89:e6:c8:bc:9f:fd:85:2b:0f:b4:c0:e4:ca:b5:a7:9a:01:05:81:93:6b:f5:8d:1c:f7:f3:77:0e:6e:53:34:92:0f:48:21:34:33:44:14:5e:4a:00:41:3a:7d:cb:38:82:c1:65:e0:79:ea:a1:05:84:b2:6e:40:19:77:1a:0e:38:4b:28:1f:34:b5:cb:ac:c5:2f:58:51:d7:ec:a8:08:0e:7c:c0:20:c1:5e:a1:4d:b1:30:17:63:0e:e7:58:8e:7f:6e:9f:a4:77:8b:1e:a2:d2:2e:1b:e9",
e: 65537
},
"RSA-OAEP"
);
var encrypter = new Jose.JoseJWE.Encrypter(cryptographer, rsa_key);
encrypter
.encrypt("hello world")
.then(function(result) {
console.log(result);
})
.catch(function(err) {
console.error(err);
});
The decimal string representing the modulus must be converted to a hexadecimal string with the proper formatting. In the following code this is done by the convert function.
The example encrypts and decrypts a plaintext and is essentially taken from the description of js-jose. The converted modulus is used for the encryption. The validity of the conversion can be cross checked e.g. here (and can of course also be concluded from the successful decryption):
function convert(modulus){
var nHex = BigInt(modulus).toString(16); // Convert from dec to hex
var nHexPadded = nHex.length % 2 ? "0" + nHex : nHex; // Pad if necessary with a leading 0
var nHexPaddedFormatted = nHexPadded.match(/.{1,2}/g).join(':'); // Separate each byte with a :
return nHexPaddedFormatted;
}
var exponent = "65537";
var modulus = "24527552248658638593238312534622665239452237617916915035327410973877933321625015819725141075075211032977064656616272935088402961419107720169032602127557052115192166251022433499097931189631750439635561603835889998309453723345666313950232348492443075827282756304618422730925476259619200114387693134398859680038905017069367126679713008966792133309640987499113594495057801427098321936394744165577110835460409347737585308896989425915113198172049505101019813693205226199749749144689080410566381237890461144281136847243342701604504885554436502186579457750948522590884398208445448252725393629705457022749423572745479491820521";
console.log(convert(modulus).replace(/(.{60})/g,'$1\n'));
var publicKey = Jose.Utils.importRsaPublicKey(
{
/*
n: "c2:4b:af:0f:2d:2b:ad:36:72:a7:91:0f:ee:30:a0:95:d5:3a:46:82:86:96:7e:42:c6:fe:8f:20:97:af:49:f6:48:a3:91:53:ac:2e:e6:ec:9a:9a:e0:0a:fb:1c:db:44:40:5b:8c:fc:d5:1c:cb:b6:9b:60:c0:a8:ac:06:f1:6b:29:5e:2f:7b:09:d9:93:32:da:3f:db:53:9c:2e:ea:3b:41:7f:6b:c9:7b:88:9f:2e:c5:dd:42:1e:7f:8f:04:f6:60:3c:fe:43:6d:32:10:ce:8d:99:cb:76:f7:10:97:05:af:28:1e:39:0f:78:35:50:7b:8e:28:22:a4:7d:11:51:22:d1:0e:ab:6b:6f:96:cb:cf:7d:eb:c6:aa:a2:6a:2e:97:2a:93:af:a5:89:e6:c8:bc:9f:fd:85:2b:0f:b4:c0:e4:ca:b5:a7:9a:01:05:81:93:6b:f5:8d:1c:f7:f3:77:0e:6e:53:34:92:0f:48:21:34:33:44:14:5e:4a:00:41:3a:7d:cb:38:82:c1:65:e0:79:ea:a1:05:84:b2:6e:40:19:77:1a:0e:38:4b:28:1f:34:b5:cb:ac:c5:2f:58:51:d7:ec:a8:08:0e:7c:c0:20:c1:5e:a1:4d:b1:30:17:63:0e:e7:58:8e:7f:6e:9f:a4:77:8b:1e:a2:d2:2e:1b:e9",
*/
n: convert(modulus), // Apply the converted modulus
e: parseInt(exponent)
},
"RSA-OAEP"
);
var privateKey = Jose.Utils.importRsaPrivateKey(
{
n:
"00:c2:4b:af:0f:2d:2b:ad:36:72:a7:91:0f:ee:30:a0:95:d5:3a:46:82:86:96:7e:42:c6:fe:8f:20:97:af:49:f6:48:a3:91:53:ac:2e:e6:ec:9a:9a:e0:0a:fb:1c:db:44:40:5b:8c:fc:d5:1c:cb:b6:9b:60:c0:a8:ac:06:f1:6b:29:5e:2f:7b:09:d9:93:32:da:3f:db:53:9c:2e:ea:3b:41:7f:6b:c9:7b:88:9f:2e:c5:dd:42:1e:7f:8f:04:f6:60:3c:fe:43:6d:32:10:ce:8d:99:cb:76:f7:10:97:05:af:28:1e:39:0f:78:35:50:7b:8e:28:22:a4:7d:11:51:22:d1:0e:ab:6b:6f:96:cb:cf:7d:eb:c6:aa:a2:6a:2e:97:2a:93:af:a5:89:e6:c8:bc:9f:fd:85:2b:0f:b4:c0:e4:ca:b5:a7:9a:01:05:81:93:6b:f5:8d:1c:f7:f3:77:0e:6e:53:34:92:0f:48:21:34:33:44:14:5e:4a:00:41:3a:7d:cb:38:82:c1:65:e0:79:ea:a1:05:84:b2:6e:40:19:77:1a:0e:38:4b:28:1f:34:b5:cb:ac:c5:2f:58:51:d7:ec:a8:08:0e:7c:c0:20:c1:5e:a1:4d:b1:30:17:63:0e:e7:58:8e:7f:6e:9f:a4:77:8b:1e:a2:d2:2e:1b:e9",
e: 65537,
d:
"37:b6:4b:f4:26:17:a8:0b:3c:c5:1f:ab:59:b9:47:d2:ae:d9:8e:ee:4e:79:48:ab:0d:34:61:06:0f:78:8b:d4:ba:ef:6b:f4:7a:22:d8:c4:6f:70:89:5d:9c:b3:a1:8b:e8:88:57:dd:07:9e:c2:2b:12:52:a3:eb:b9:a8:24:01:7e:53:2b:7a:34:50:d7:0c:75:d8:69:a3:87:dd:4b:fc:c1:c3:2f:bd:0e:57:16:8d:ea:de:8e:de:ff:e4:9a:9f:aa:e8:d2:5f:b3:27:ef:f9:ca:50:97:2e:fd:99:1c:34:dd:0c:bb:dd:d0:b9:bf:4f:dc:9d:de:94:50:66:2c:58:7e:c2:31:8b:41:56:49:6a:e6:11:14:53:a1:45:0d:15:8b:26:79:0f:c9:dc:ac:dc:c7:bc:55:2c:96:ed:a7:29:09:04:ee:00:74:60:e1:bc:97:7b:0a:b6:f2:83:82:79:65:e0:aa:88:9f:90:b0:0d:76:4d:3c:08:7e:a5:05:19:d4:8b:54:d3:f1:c1:a3:e3:a5:1e:aa:d6:c4:94:ad:6c:b3:8f:85:06:8a:6f:52:f8:a3:c3:e0:8d:67:35:2f:d4:18:fc:70:f4:71:bf:18:88:d6:a7:b7:04:8e:d3:06:ca:83:c3:2d:21:98:65:c9:41:2c:77:bf:4c:7c:8c:2c:01",
p:
"00:fa:d6:06:46:5c:04:70:e6:ec:47:02:96:02:a5:e2:41:9d:bd:7b:97:28:a4:c5:3b:b5:9b:0a:6b:7d:b6:44:8a:28:1e:d1:ef:cb:44:ef:eb:4d:08:74:80:f5:cf:3b:b7:40:10:60:c9:18:1e:a5:76:4b:41:37:06:b2:71:03:60:25:77:db:d0:b2:21:dc:b0:32:90:a2:10:9a:d5:e6:e3:11:42:a1:9a:7a:26:3c:d3:12:56:db:25:07:69:be:ae:2c:b9:33:6c:29:e3:65:b9:5b:05:84:05:e6:da:c4:f4:3f:ab:84:60:6e:f0:5f:ba:a8:98:8f:72:2c:c8:40:d1",
q:
"00:c6:4b:ac:fe:40:1c:dc:6c:78:07:cc:3e:db:4e:d5:d0:17:3b:8f:04:f0:ae:c4:22:0d:8b:0a:4d:0f:9e:fe:c7:e6:38:b5:53:ba:a9:e8:f0:47:28:14:25:95:6a:79:ab:db:86:97:82:c5:1e:bd:80:a5:aa:a2:b7:a5:c7:48:17:c4:d9:c7:4f:50:2a:69:67:15:4c:0b:f5:e6:fb:20:23:5d:ea:ae:6c:c6:74:ba:cc:f8:06:2b:41:1f:b6:3f:2a:93:fa:f9:e1:ee:93:c3:92:ad:49:c7:8f:db:72:ff:6b:f0:f0:d6:2f:83:ce:1c:82:16:89:57:01:9f:49:2f:99",
dp:
"57:d4:c1:75:b9:9a:c4:7d:d7:96:35:cd:99:37:c4:b5:fd:29:f0:30:c9:c6:88:59:94:09:a9:e8:61:a8:84:ef:6b:84:ff:35:dc:13:53:7f:2d:06:1c:e5:5b:2d:29:57:cd:52:ee:d0:fb:65:1f:c3:00:2e:e1:b9:b2:99:e7:f8:ae:a5:fd:8e:62:11:81:59:21:1b:8b:e4:0c:93:81:b9:58:bd:e0:20:5b:4d:30:57:28:40:c9:93:79:b9:09:4f:ab:d1:5d:b4:2e:26:b5:e3:e5:7f:54:ef:4c:1a:a6:84:70:16:fa:cf:59:89:49:bb:ee:75:1d:25:79:90:d5:41",
dq:
"00:ab:eb:a8:8c:b7:21:4e:aa:6c:56:b6:6a:38:d1:dc:e6:91:7d:fd:bd:96:be:af:25:a7:00:49:6a:0e:85:16:f8:51:4e:11:48:0a:aa:8d:5e:e5:12:86:85:1f:4a:35:3b:1f:15:4d:fe:fe:d0:6c:14:41:8d:f3:8d:ad:99:5d:93:de:03:c2:9d:ad:2f:58:3b:1b:67:d7:66:d7:60:1a:b9:0f:10:0d:32:19:cd:d2:b7:2a:c2:8e:75:e3:fc:aa:3f:4c:15:68:d8:cd:74:27:37:e0:2d:fb:6b:6a:24:05:f7:9b:e9:f2:89:37:89:57:86:21:eb:e9:17:6a:f6:94:e1",
qi:
"0a:ed:5f:30:67:d5:e5:6e:4a:7a:35:49:fe:16:2f:1e:91:2b:39:c3:01:d3:d4:c0:4d:b3:fc:08:b0:66:e9:44:10:9e:5b:5a:ea:83:a5:9c:95:7a:58:70:35:28:e5:4d:ba:19:de:0d:66:f9:db:5c:f6:5b:24:27:9d:0b:2d:44:40:eb:33:3a:19:e2:1d:c0:b0:16:99:d1:c1:52:84:02:d6:67:06:32:f8:4d:cb:42:9f:7c:8a:e0:ad:df:40:6f:e4:8c:f6:f6:9e:1d:bd:43:e3:38:91:a2:d0:9e:60:ff:9d:8c:fb:72:5b:df:95:30:17:d2:f2:cb:7d:92:56:0a"
},
"RSA-OAEP"
);
// Example based on https://github.com/square/js-jose#example-encryption
var cryptographer = new Jose.WebCryptographer();
var encrypter = new Jose.JoseJWE.Encrypter(cryptographer, publicKey);
encrypter
.encrypt("The quick brown fox jumps over the lazy dog")
.then(function(jwe) {
console.log(jwe.replace(/(.{60})/g,'$1\n'));
var decrypter = new Jose.JoseJWE.Decrypter(cryptographer, privateKey);
decrypter
.decrypt(jwe)
.then(function(jwe_plain_text) {
console.log(jwe_plain_text.replace(/(.{60})/g,'$1\n'));
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-jose/0.2.2/jose.min.js"></script>

How to add digest from sha256 to string in flutter?

I'm passing password into sha256. I successfully create sha256 and can also print it. The problem begins when I'm trying to convert digest.bytes into a string and append it.
import 'package:crypto/crypto.dart';
var url = "http://example_api.php?";
url += '&hash=';
// hash the password
var bytes = utf8.encode(password);
var digest = sha256.convert(bytes);
print("Digest as hex string: $digest");
url += String.fromCharCodes(digest.bytes);
This is printed: Digest as hex string: 03ac674216f3e15c761ee1a5e255f067953623c8b388b4459e13f978d7c846f4
This is appended to url: ¬gBóá\vá¥âUðg6#ȳ´Eùx×ÈFô
What am I doing wrong? I also tried utf8.decode method but using it gives me an error.
When you print digest, the print method will call digest.toString(), which is implemented to return a string of the digest bytes using a hexadecimal representation. If you want the same thing you have several options:
Call digest.toString() explicitly (or implicitly)
final digestHex = digest.toString(); // explicitly
final digestHex = '$digest'; // implicitly
Map the byte array to its hexadecimal equivalent
final digestHex = digest.bytes.map((b) => b.toRadixString(16).padLeft(2, '0')).join();
Use the convert package (this is what the crypto package does)
import 'package:convert/convert.dart';
...
final digestHex = hex.encode(digest.bytes);
The reason you are getting an error using utf8.decode is that your digest isn't an encoded UTF-8 string but a list of bytes that for all intents and purposes are completely random. You are trying to directly convert the bytes into a string, and doing so is easier if you can assume that they already represent a valid string. With the byte output from a hashing algorithm, though, you cannot safely make such an assumption.
However, if for some reason you still want to use this option, use the second optional parameter for utf8.decode to force it to try and decode the bytes anyway:
final digestString = utf8.decode(bytes, allowMalformed: true);
For reference, a byte list of [1, 255, 47, 143, 6, 80, 33, 202] results in "�/�P!�" where "�" represents an invalid/control character. You do not want to use this option, especially where the string will become part of a URL (as it's virtually guaranteed that the resulting string will not be web-safe).
For the hexadecimal representation of a Digest object, please explicitly call Digest.toString() (though in formatted strings, i.e. "url${digest}", this is done for you implicitly).
I'm frankly not familiar with String.fromCharCode, but I think it's looking for UTF-16 and not UTF-8 bits. I wrote a terminal example to show this, and how the outputs differ.
import 'dart:core';
import 'dart:convert';
import 'package:crypto/crypto.dart';
void main() {
const String password = "mypassword";
// hash the password
var bytes = utf8.encode(password);
var digest = sha256.convert(bytes);
// different formats
var bytesDigest = digest.bytes;
var hexDigest = digest.toString();
String url = "http://example_api.php?hash=";
print(url + hexDigest);
print(url + String.fromCharCodes(bytesDigest));
}
Output:
> dart test.dart
http://example_api.php?hash=89e01536ac207279409d4de1e5253e01f4a1769e696db0d6062ca9b8f56767c8
http://example_api.php?hash=à6¬ ry#Ö,©¸õggÈ

AES encryption using CryptoSwift and CryptoJS

I was to trying encrypt a text using CryptoSwift for ios application, and CryptoJS for web application, which has to be decrypted in Java platform. I could able to encrypt successfully in javascript by using the following code.
var message = "Hello"
var password = "samplepasswordky"
function encrypt(message, password) {
var salt = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
var key = CryptoJS.PBKDF2(pass, salt, {
keySize: keySize/32,
iterations: iterations
});
var iv = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
var encrypted = CryptoJS.AES.encrypt(msg, key, {
iv: iv
});
var encryptedMessage = encrypted.ciphertext.toString(CryptoJS.enc.Base64);
return encryptedMessage;
}
For the same in CryptoSwift I am doing the following, but I could not decrypt the text in Java.
let salt: [UInt8] = Array("0000000000000000".utf8)
let password: [UInt8] = Array("samplepasswordky".utf8)
let iv: [UInt8] = Array("0000000000000000".utf8)
let derivedKey = try! PKCS5.PBKDF2(password: password, salt: salt , iterations: 100, keyLength: 16, variant: .sha1).calculate()
let encrypted = try! AES(key: derivedKey, blockMode: CBC(iv: iv), padding: .pkcs5).encrypt(input)
print(encrypted.toHexString())
Kindly help me to make this work.
This line:
var salt = CryptoJS.enc.Hex.parse("00000000000000000000000000000000");
Is not the same as this line:
let salt: [UInt8] = Array("0000000000000000".utf8)
The utf8 encoding of "0000000000000000" is, in hex, 30303030303030303030303030303030 (0x30 is the UTF-8 encoding of the character "0").
What you meant to use here is Array(repeating: UInt8(0), count: 16).
You're also outputting a Base64 string in JavaScript, and a hex string in Swift, which are not the same things.
Unrelated side-note:
This implementation is working pretty hard to get little security. If your password is static, you could do much better by using a random key (i.e. 32 completely random bytes 0-255, not a string of characters). PKBDF2 isn't really buying you much here, excepting slowing down the system (not slowing down the attacker; just your app). Adding a random IV would significantly improve this system as well with little cost.

How can I generate a random unicode character in Swift?

My current attempts at creating a random unicode character generate have failed with errors such as those mentioned in my other question here. It's obviously not as simple as just generating a random number.
Question: How can I generate a random unicode character in Swift?
Unicode Scalar Value
Any Unicode code point except high-surrogate and low-surrogate code
points. In other words, the ranges of integers 0 to D7FF and E000
to 10FFFF inclusive.
So, I've made a small code's snippet. See below.
This code works
func randomUnicodeCharacter() -> String {
let i = arc4random_uniform(1114111)
return (i > 55295 && i < 57344) ? randomUnicodeCharacter() : String(UnicodeScalar(i))
}
randomUnicodeCharacter()
This code doesn't work!
let N: UInt32 = 65536
let i = arc4random_uniform(N)
var c = String(UnicodeScalar(i))
print(c, appendNewline: false)
I was a little bit confused with this and this. [Maximum value: 65535]
static func randomCharacters(withLength length: Int = 20) -> String {
let base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var randomString: String = ""
for _ in 0..<length {
let randomValue = arc4random_uniform(UInt32(base.characters.count))
randomString += "\(base[base.index(base.startIndex, offsetBy: Int(randomValue))])"
}
return randomString
}
Here you can modify length (Int) and use this for generating random characters.