How to get Modulus and Exponent from RSA private key in iOS Swift? - encryption

How to parse RSA private key in order to get modulus(n) and exponent(e) from it?
RSA Private Key Example --->
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEApSrpu9xy2MGlmKBpSarF5w2vGk77DXmU3brJyJxKOLzf4ARo
zjNcfO87T/8F23ES5iOU6z8Y6HUfLKkDHa2IwfraUWDoMudDZTCrROH4bA74TFo/
Mlhh1awotNqB1D24H3wnhkd87BcLVZWv2qDV1SVmWu9xW6GrffyjkWojkqzYwSHT
viPKfWzsQ6cbedN7WUyUZt+78YZlY13fMoXLY26xgxuBYld2vLI3qHooJnRTf32u
8aqM+X52h0/6MoYJgc9zwUTNBWrd3G6GHnRXbYpao56IYAoUtwBJHzQ5md0FVUKH
Vqfk8eJp3YKujYyrpSFKj7rKI/pHHZawnmPQLQIDAQABAoIBABNisgRGn4QpVlJP
oYvv60JvLLodwwGV348WuVA+Z8e5A127psFs7dIMEh4VhI54+wrf6j6iLT47YOlQ
/PiiwYZi9vTONvKiihp6V9/B1fJ431O20+wIy5LUngJ8EvjiNZYccFcmVNcw7Tei
Vf2HGxHlTdomeFuU4hfraxdKKdqxFnvT/lfbo/uX5tN660DSAGd1xRmUf08w9OUU
nG0LVk20hz/dn+WUnF+GnZfFjVI06IwvfMiDN2Z7zXP+IBOH7fDwQZUy6ExnesnR
79iswCEyVx0FFveAMpHvLMUhEKg2iYIRXzD/Oy4sX5pDZT2fE289MtkgZbHxXDLJ
cbucSVECgYEA1/tjvX1zdxGG9wT4zld+WYRa9ax+EeECWqOXn95c3BY3bTUlMQlX
4HlOiYUAzwIf58LaKuTYRjUiv9J9Axw7jkxd4P6Y7BYOatdAfv8PG1Y+SA7r0utM
D37DCesroD0C4IuRc+YzVvjdtvsNDgpKf5cXFKWoNQVX4t4UbUcRaA8CgYEAw8VC
vZieW/eM8yKqna8BFt3siun8ucieh/PGutBfq8W7sdqDb0JZpdWYOj12P/0/9gSG
dlaSpTq7svxTj9wdb5kU1Yp56CWM7wy+adCQvWyMXJ6s/CA8SZM9KCmWt6w4vRAm
+6oElxyT4exYFvXebRN6GXs0TWucuqQ64/z+6AMCgYBn1kC5lVqx4AdXM1i7O21P
dEaW3nst9VPAZ+45uhpC5Zt4MZjT3n4VObz8eKlO3OKh9hgVjzg7aMhwGK5plGU9
oJFx3nV+64u66gnkBJQqvGftFN9j5CQJPxRd7GZo/2wmsHMZmY8NPVC67C/2lBQF
C4rZLluUQiFivQptD0HbGQKBgEOAT5vZ9LhXKdVnnZaTEfgVewsG1OomH2tXBa3C
TUqH+ki/xFPnd8uzUzK5oH090AD+3HIPNa8dCj0Tvag7yDaDfOiIP7JoyChgp4MK
s+1scRU6bQDeCIuB5jNj66DXFBU0bYyWudB0vRTIDjOUgSXw8ke48HbFZRwBpoCX
6jiLAoGAGhHvi9NUPaWv3fpPTQnbo2aaYSXyniW7s5bGgUQmIjuFDo/GHomIh6T/
RJgyQYxBlUqCLs/C6YABa6hce/qMSS0JEt10uqknYfYjZ3jZEZSKPy8vpxaZX6ot
dHruKemEoO1yLKhGI56KCdhWMrfsn7VbY+wCX2S1J/MZjWBIKNY=
-----END RSA PRIVATE KEY-----

func parsePrivateSecKey(privateKey: SecKey) -> (mod: Data, exp: Data) {
let pubAttributes = SecKeyCopyAttributes(privateKey) as! [String: Any]
print("pubAttributes----\(pubAttributes)")
// let keydata = pubAttributes[kSecPrivateKeyAttrs as String] as! [String: Any]
// print("----key data ------===\(keydata)")
let data = Data(base64Encoded: "")
// Check that this is really an RSA key
guard Int(pubAttributes[kSecAttrKeyType as String] as! String)
== Int(kSecAttrKeyTypeRSA as String) else {
// throw "Tried to parse non-RSA key as RSA key"
return (mod: data!, exp: data!)
}
// Check that this is really a private key
guard Int(pubAttributes[kSecAttrKeyClass as String] as! String)
== Int(kSecAttrKeyClassPrivate as String)
else {
// throw "Tried to parse non-private key as private key"
return (mod: data!, exp: data!)
}
let keySize = pubAttributes[kSecAttrKeySizeInBits as String] as! Int
// Extract values
let pubData = pubAttributes[kSecValueData as String] as! Data
print("pubData---\(pubData)")
// SecKeyCopyModulus
//Find modulus data length
let modulusLengthData = pubData.subdata(in: 9..<11)
print(modulusLengthData as NSData)
let modulusLength = BigUInt(modulusLengthData)
print("mod lenth ===\(modulusLength)")
//find MODULUS
var modulus = pubData.subdata(in: 11..<(Int(modulusLength) + 11))
let reqMod = BigUInt(modulus)
print("final modulus====\(reqMod)")
//Find exponent data length
var expDataLength = pubData.subdata(in: (Int(modulusLength) + 11 + 7)..<(Int(modulusLength) + 11 + 7 + 1))
print(expDataLength as NSData)
var bytes_to_find : [UInt8] = [0xFF] //0xFF = 255 size
let datafind = Data(bytes: &bytes_to_find, count: bytes_to_find.count)
let range = expDataLength.range(of: datafind, options: [], in: Range(NSRange(location: 0, length: expDataLength.count)))
var exponentLength = BigUInt(expDataLength)
print("exponent lenth ===\(exponentLength)")
//Find EXPONENT
var exponent = pubData.subdata(in: (Int(modulusLength) + 11 + 7 + 1)..<(Int(modulusLength) + 11 + 7 + 1 + Int(exponentLength)))
//check if its size is 255 or more and get data length accordingly
if range == nil {
expDataLength = pubData.subdata(in: (Int(modulusLength) + 11 + 7)..<(Int(modulusLength) + 11 + 7 + 2))
print("0xFF not found...")
exponentLength = BigUInt(expDataLength)
print("exponent lenth ===\(exponentLength)")
//Find EXPONENT
exponent = pubData.subdata(in: (Int(modulusLength) + 11 + 7 + 1)..<(Int(modulusLength) + 11 + 7 + 2 + Int(exponentLength)))
}
let reqExp = BigUInt(exponent)
print("final exponent====\(reqExp)")
if modulus.count > keySize / 8 { // --> 257 bytes
modulus.removeFirst(1)
}
return (mod: modulus, exp: exponent)
}

Related

Calling Netsuite SOAP .wsdl from C# .Net Core

First of all, I found this link which was a HUGE help to get this working.
https://medium.com/#benwmills/using-the-netsuite-suitetalk-api-with-net-core-net-standard-40f1a4464da1
But wanted to post my findings - in case it helps anyone else.
Step 1: Add a Service Reference to your project (WCF Web Service)
Step 2: Create NetSuitePortTypeClient and Open it (use your own account specific)
NetSuitePortTypeClient nsptc = new NetSuitePortTypeClient(NetSuitePortTypeClient.EndpointConfiguration.NetSuitePort, "https://########.suitetalk.api.netsuite.com/services/NetSuitePort_2021_2");
await nsptc.OpenAsync();
Step 3: Create a Transaction Search in this example
TransactionSearch tranSearch = new TransactionSearch();
TransactionSearchBasic tranSearchBasic = new TransactionSearchBasic();
SearchStringField searchstringfield = new SearchStringField();
searchstringfield.#operator = SearchStringFieldOperator.#is;
searchstringfield.operatorSpecified = true;
searchstringfield.searchValue = "$$$$$$";
tranSearchBasic.tranId = searchstringfield;
tranSearch.basic = tranSearchBasic;
Step 4: Call the Search
searchResponse sresponse = await nsptc.searchAsync(CreateTokenPassport(), null, null, null, tranSearch);
AND Here is the CreateTokenPassword function
public TokenPassport CreateTokenPassport()
{
string account = "account";
string consumerKey = "ckey";
string consumerSecret = "csecret";
string tokenId = "token";
string tokenSecret = "tokensecret";
string nonce = ComputeNonce();
long timestamp = ComputeTimestamp();
TokenPassportSignature signature = ComputeSignature(account, consumerKey, consumerSecret, tokenId, tokenSecret, nonce, timestamp);
TokenPassport tokenPassport = new TokenPassport();
tokenPassport.account = account;
tokenPassport.consumerKey = consumerKey;
tokenPassport.token = tokenId;
tokenPassport.nonce = nonce;
tokenPassport.timestamp = timestamp;
tokenPassport.signature = signature;
return tokenPassport;
}
You've left out the ComputeNonce, ComputeTimestamp, ComputeSignature functions so this code doesn't work...
Here is full code from example of calling NetSuite SOAP using C#:
public TokenPassport CreateTokenPassport()
{
string account = DataCollection["login.acct"];
string consumerKey = DataCollection["login.tbaConsumerKey"];
string consumerSecret = DataCollection["login.tbaConsumerSecret"];
string tokenId = DataCollection["login.tbaTokenId"];
string tokenSecret = DataCollection["login.tbaTokenSecret"];
string nonce = ComputeNonce();
long timestamp = ComputeTimestamp();
TokenPassportSignature signature = ComputeSignature(account, consumerKey, consumerSecret, tokenId, tokenSecret, nonce, timestamp);
TokenPassport tokenPassport = new TokenPassport();
tokenPassport.account = account;
tokenPassport.consumerKey = consumerKey;
tokenPassport.token = tokenId;
tokenPassport.nonce = nonce;
tokenPassport.timestamp = timestamp;
tokenPassport.signature = signature;
return tokenPassport;
}
private string ComputeNonce()
{
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] data = new byte[20];
rng.GetBytes(data);
int value = Math.Abs(BitConverter.ToInt32(data, 0));
return value.ToString();
}
private long ComputeTimestamp()
{
return ((long) (DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}
private TokenPassportSignature ComputeSignature(string compId, string consumerKey, string consumerSecret,
string tokenId, string tokenSecret, string nonce, long timestamp)
{
string baseString = compId + "&" + consumerKey + "&" + tokenId + "&" + nonce + "&" + timestamp;
string key = consumerSecret + "&" + tokenSecret;
string signature = "";
var encoding = new System.Text.ASCIIEncoding();
byte[] keyBytes = encoding.GetBytes(key);
byte[] baseStringBytes = encoding.GetBytes(baseString);
using (var hmacSha1 = new HMACSHA1(keyBytes))
{
byte[] hashBaseString = hmacSha1.ComputeHash(baseStringBytes);
signature = Convert.ToBase64String(hashBaseString);
}
TokenPassportSignature sign = new TokenPassportSignature();
sign.algorithm = "HMAC-SHA1";
sign.Value = signature;
return sign;
}

CCCrypt maximum time it returns nil. What is the problem in Encryption

I trying to write an encryption (AESCBC128) function based on CCCrypt and the CCCrypt is generating a random value.
for example, when I pass 016768821221 to function it'll return "0oTPFcKNWABTpBGgLlzsjw==" for the same iv and Key.
here's the iv: "khabbababab" and the key is : "khabbababab"
why it returns nil. The encryption is correct but some times it returns nil
extension String {
func aesEncrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = self.data(using: String.Encoding.utf8),
let cryptData = NSMutableData(length: Int((data.count)) + kCCBlockSizeAES128) {
let keyLength = kCCKeySizeAES128
let operation: CCOperation = UInt32(kCCEncrypt)
let algoritm: CCAlgorithm = CCOptions(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
CCOptions(options),
(keyData as NSData).bytes, keyLength,
iv,
(data as NSData).bytes, data.count,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
print(String(data: data, encoding: .utf8) as Any)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let base64cryptString = cryptData.base64EncodedString(options: .lineLength64Characters)
print("succccc")
return base64cryptString
}
else {
print("nill nill llllllllll")
return nil
}
}
return nil
}
func aesDecrypt(key:String, iv:String, options:Int = kCCOptionPKCS7Padding) -> String? {
if let keyData = key.data(using: String.Encoding.utf8),
let data = NSData(base64Encoded: self, options: .ignoreUnknownCharacters),
let cryptData = NSMutableData(length: Int((data.length)) + kCCBlockSizeAES128) {
let keyLength = size_t(kCCKeySizeAES128)
let operation: CCOperation = UInt32(kCCDecrypt)
let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128)
let options: CCOptions = UInt32(options)
var numBytesEncrypted :size_t = 0
let cryptStatus = CCCrypt(operation,
algoritm,
options,
(keyData as NSData).bytes, keyLength,
iv,
data.bytes, data.length,
cryptData.mutableBytes, cryptData.length,
&numBytesEncrypted)
if UInt32(cryptStatus) == UInt32(kCCSuccess) {
cryptData.length = Int(numBytesEncrypted)
let unencryptedMessage = String(data: cryptData as Data, encoding:String.Encoding.utf8)
return unencryptedMessage
}
else {
return nil
}
}
return nil
}
Your aesEncrypt always passes a keylength of 16 to CCCrypt without checking that the key actually has at least 16 bytes of data.

Encrypt/Decrypt String Kotlin

I've created this two extensions in Kotlin to Encrypt/Decrypt strings:
fun String.encrypt(seed : String): String {
val keyGenerator = KeyGenerator.getInstance("AES")
val secureRandom = SecureRandom.getInstance("SHA1PRNG")
secureRandom.setSeed(seed.toByteArray())
keyGenerator.init(128, secureRandom)
val skey = keyGenerator.generateKey()
val rawKey : ByteArray = skey.encoded
val skeySpec = SecretKeySpec(rawKey, "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, skeySpec)
val byteArray = cipher.doFinal(this.toByteArray())
return byteArray.toString()
}
fun String.decrypt(seed : String): String {
val keyGenerator = KeyGenerator.getInstance("AES")
val secureRandom = SecureRandom.getInstance("SHA1PRNG")
secureRandom.setSeed(seed.toByteArray())
keyGenerator.init(128, secureRandom)
val skey = keyGenerator.generateKey()
val rawKey : ByteArray = skey.encoded
val skeySpec = SecretKeySpec(rawKey, "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, skeySpec)
val byteArray = cipher.doFinal(this.toByteArray())
return byteArray.toString()
}
for some reason I'm getting the following exception:
javax.crypto.IllegalBlockSizeException: last block incomplete in decryption
What I'm doing wrong?
AES Encryption / Decryption using base64 key, salt and iv (Initialization Vector).
object AESEncyption {
const val secretKey = "tK5UTui+DPh8lIlBxya5XVsmeDCoUl6vHhdIESMB6sQ="
const val salt = "QWlGNHNhMTJTQWZ2bGhpV3U=" // base64 decode => AiF4sa12SAfvlhiWu
const val iv = "bVQzNFNhRkQ1Njc4UUFaWA==" // base64 decode => mT34SaFD5678QAZX
fun encrypt(strToEncrypt: String) : String?
{
try
{
val ivParameterSpec = IvParameterSpec(Base64.decode(iv, Base64.DEFAULT))
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
val spec = PBEKeySpec(secretKey.toCharArray(), Base64.decode(salt, Base64.DEFAULT), 10000, 256)
val tmp = factory.generateSecret(spec)
val secretKey = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec)
return Base64.encodeToString(cipher.doFinal(strToEncrypt.toByteArray(Charsets.UTF_8)), Base64.DEFAULT)
}
catch (e: Exception)
{
println("Error while encrypting: $e")
}
return null
}
fun decrypt(strToDecrypt : String) : String? {
try
{
val ivParameterSpec = IvParameterSpec(Base64.decode(iv, Base64.DEFAULT))
val factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1")
val spec = PBEKeySpec(secretKey.toCharArray(), Base64.decode(salt, Base64.DEFAULT), 10000, 256)
val tmp = factory.generateSecret(spec);
val secretKey = SecretKeySpec(tmp.encoded, "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
return String(cipher.doFinal(Base64.decode(strToDecrypt, Base64.DEFAULT)))
}
catch (e : Exception) {
println("Error while decrypting: $e");
}
return null
}
}
iOS swift
Following Maarten Bodews guides I fix the issues as:
fun String.encrypt(password: String): String {
val secretKeySpec = SecretKeySpec(password.toByteArray(), "AES")
val iv = ByteArray(16)
val charArray = password.toCharArray()
for (i in 0 until charArray.size){
iv[i] = charArray[i].toByte()
}
val ivParameterSpec = IvParameterSpec(iv)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
val encryptedValue = cipher.doFinal(this.toByteArray())
return Base64.encodeToString(encryptedValue, Base64.DEFAULT)
}
fun String.decrypt(password: String): String {
val secretKeySpec = SecretKeySpec(password.toByteArray(), "AES")
val iv = ByteArray(16)
val charArray = password.toCharArray()
for (i in 0 until charArray.size){
iv[i] = charArray[i].toByte()
}
val ivParameterSpec = IvParameterSpec(iv)
val cipher = Cipher.getInstance("AES/GCM/NoPadding")
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
val decryptedByteValue = cipher.doFinal(Base64.decode(this, Base64.DEFAULT))
return String(decryptedByteValue)
}
To encode your ciphertext use base 64 or hexadecimals. The Java API contains a Base64 class, so you're probably best off using that.
byte[]#toString doesn't do what you expect it to do; it simply returns a representation of the byte array reference, not the contents of the byte array.
Besides that:
don't use SecureRandom to derive a key, try and lookup PBKDF2;
explicitly use a mode of operation such as "AES/GCM/NoPadding";
use a unique IV, and a random IV if you decide to use CBC (usually insecure);
don't use toByteArray without explicitly selecting a character encoding for the message.
The easiest way of implementing AES Encryption and Decryption in Android is to copy this class in your projects.
Encrypt Strings
Please copy the AESUtils class in your project first and then you can use it like this.
String encrypted = "";
String sourceStr = "This is any source string";
try {
encrypted = AESUtils.encrypt(sourceStr);
Log.d("TEST", "encrypted:" + encrypted);
} catch (Exception e) {
e.printStackTrace();
}
Decrypt Strings
String encrypted = "ANY_ENCRYPTED_STRING_HERE";
String decrypted = "";
try {
decrypted = AESUtils.decrypt(encrypted);
Log.d("TEST", "decrypted:" + decrypted);
} catch (Exception e) {
e.printStackTrace();
}
AESUtils Class
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESUtils
{
private static final byte[] keyValue =
new byte[]{'c', 'o', 'd', 'i', 'n', 'g', 'a', 'f', 'f', 'a', 'i', 'r', 's', 'c', 'o', 'm'};
public static String encrypt(String cleartext)
throws Exception {
byte[] rawKey = getRawKey();
byte[] result = encrypt(rawKey, cleartext.getBytes());
return toHex(result);
}
public static String decrypt(String encrypted)
throws Exception {
byte[] enc = toByte(encrypted);
byte[] result = decrypt(enc);
return new String(result);
}
private static byte[] getRawKey() throws Exception {
SecretKey key = new SecretKeySpec(keyValue, "AES");
byte[] raw = key.getEncoded();
return raw;
}
private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKey skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private static byte[] decrypt(byte[] encrypted)
throws Exception {
SecretKey skeySpec = new SecretKeySpec(keyValue, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static byte[] toByte(String hexString) {
int len = hexString.length() / 2;
byte[] result = new byte[len];
for (int i = 0; i < len; i++)
result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2),
16).byteValue();
return result;
}
public static String toHex(byte[] buf) {
if (buf == null)
return "";
StringBuffer result = new StringBuffer(2 * buf.length);
for (int i = 0; i < buf.length; i++) {
appendHex(result, buf[i]);
}
return result.toString();
}
private final static String HEX = "0123456789ABCDEF";
private static void appendHex(StringBuffer sb, byte b) {
sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
}
}
You can Encrypt and Decrypt in Kotlin like this
first you need:
val SECRET_KEY = "secretKey"
val SECRET_IV = "secretIV"
after that
Encrypt:
private fun String.encryptCBC(): String {
val iv = IvParameterSpec(SECRET_IV.toByteArray())
val keySpec = SecretKeySpec(SECRET_KEY.toByteArray(), "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING")
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv)
val crypted = cipher.doFinal(this.toByteArray())
val encodedByte = Base64.encode(crypted, Base64.DEFAULT)
return String(encodedByte)
}
and Decrypt:
private fun String.decryptCBC(): String {
val decodedByte: ByteArray = Base64.decode(this, Base64.DEFAULT)
val iv = IvParameterSpec(SECRET_IV.toByteArray())
val keySpec = SecretKeySpec(SECRET_KEY.toByteArray(), "AES")
val cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING")
cipher.init(Cipher.DECRYPT_MODE, keySpec, iv)
val output = cipher.doFinal(decodedByte)
return String(output)
}
after that you can use it like this:
val strEncrypt = edt.text.toString().encryptCBC()
val strDecrypted = strEncrypt?.decryptCBC()
Following MarcForn guide I reduce it like this this:
const val encryptionKey = "ENCRYPTION_KEY"
fun String.cipherEncrypt(encryptionKey: String): String? {
try {
val secretKeySpec = SecretKeySpec(encryptionKey.toByteArray(), "AES")
val iv = encryptionKey.toByteArray()
val ivParameterSpec = IvParameterSpec(iv)
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec)
val encryptedValue = cipher.doFinal(this.toByteArray())
return Base64.encodeToString(encryptedValue, Base64.DEFAULT)
} catch (e: Exception) {
e.message?.let{ Log.e("encryptor", it) }
}
return null
}
fun String.cipherDecrypt(encryptionKey: String): String? {
try {
val secretKeySpec = SecretKeySpec(encryptionKey.toByteArray(), "AES")
val iv = encryptionKey.toByteArray()
val ivParameterSpec = IvParameterSpec(iv)
val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding")
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec)
val decodedValue = Base64.decode(this, Base64.DEFAULT)
val decryptedValue = cipher.doFinal(decodedValue)
return String(decryptedValue)
} catch (e: Exception) {
e.message?.let{ Log.e("decryptor", it) }
}
return null
}

Range of all linkAttributed String in MutableAttributedString in swift

I have a mutableAttributedString in which few strings are linkAttributed,I want to find the Range of all link attributed string. How to do that in swift3 ?
When user start type # in textview i show list of few name. If user select any row then following method gets called.
func didSelectMemberId(_ model: BaseModel) {
var fullName = ""
if model.entityType == ReceiverType.Active.rawValue{
fullName = model.name
}else{
fullName = AtMention + model.name + " " + model.name2
}
let attributedString = NSMutableAttributedString(string:fullName, attributes:[NSFontAttributeName:(appNeedsAutoResize ? (UIUtils.getFontForApproprieteField(.headlineWithoutBold).font) : UIFont.systemFont(ofSize: 14))])
attributedString.addAttribute(NSLinkAttributeName, value: "connectmention://\(model.entityId.stringValue())", range: NSRange(location: 0, length: fullName.length))
attributedString.append(NSAttributedString(string: emptySpaceStringByUC, attributes:[NSFontAttributeName:(appNeedsAutoResize ? (UIUtils.getFontForApproprieteField(.headlineWithoutBold).font) : UIFont.systemFont(ofSize: 14))]))
self.composeBar.textView.textStorage.insert(attributedString, at:self.composeBar.textView.selectedRange.location)
}
self.composeBar.textView.selectedRange = NSMakeRange(self.composeBar.textView.selectedRange.location+fullName.length, 0 )
To get the link proprty I am using the following method
func getlinkActionRange(attributeString: NSAttributedString) -> [MentionStruct] {
var arrMentions = [MentionStruct]()
_ = attributeString.enumerateAttribute(NSLinkAttributeName, in: NSRange.init(location: 0, length: attributeString.length), options: [], using: { (value, range, stop) in
if let url = value {
let occurrence = (attributeString.string as NSString).substring(with:range)
arrMentions.append(MentionStruct(link: url as! String, text: occurrence, range: range))
}
})
return arrMentions
}
If user type anything after inserting that name , that type string also coming.

Convert string start with 0 to 2 decimal place asp.net?

I have this string:
Dim value as String = "0.11209176170341301"
And tried to use this code to convert the string into decimal with two places:
Dim value as String = "0.11209176170341301"
Dim valueInDecimal As Decimal
If [Decimal].TryParse(value, valueInDecimal) Then
Console.WriteLine(valueInDecimal.ToString("0:0.#"))
End If
I get this result:
11209176170341301D
I need to get this:
0.11
What I'm doing wrong?
I want to get as result a decimal with two placesfrom the string value
You can use basic string operations also:
string value = "0.11209176170341301";
var parts = value.Split('.');
var floatingPart = parts[1].Substring(0, 2);
var truncatedValue = parts[0] + "," + floatingPart;
decimal d = decimal.Parse(truncatedValue);
string s = d.ToString();
Console.Write(s);
Console.Read();
If you are only needed it as string then you can just truncate it as string then it will be easier like:
string value = "0.11209176170341301";
var parts = value.Split('.');
var floatingPart = parts[1].Substring(0, 2);
var truncatedValue = parts[0] + "," + floatingPart;
Console.Write(truncatedValue);
Or even you do not convert '.' to ',' then it will be like this:
string value = "0.11209176170341301";
var parts = value.Split('.');
var floatingPart = parts[1].Substring(0, 2);
var truncatedValue = string.Join(".",parts[0],floatingPart);
Console.Write(truncatedValue);
Use Math.Round function
var x = "0.11209176170341301";
Console.Write(Math.Round(Convert.ToDecimal(x), 2));

Resources