From e911742991293495eee6663b415d1011720f2b68 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Sun, 8 Dec 2019 18:51:19 +0330 Subject: [PATCH 01/13] Add CSR with EC and ECDSA algo --- .../src/main/java/com/RNRSA/CsrHelper.java | 121 ++++++++++++++++++ .../java/com/RNRSA/RNRSAKeychainModule.java | 23 ++++ android/src/main/java/com/RNRSA/RSA.java | 65 +++++++++- index.d.ts | 1 + 4 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 android/src/main/java/com/RNRSA/CsrHelper.java diff --git a/android/src/main/java/com/RNRSA/CsrHelper.java b/android/src/main/java/com/RNRSA/CsrHelper.java new file mode 100644 index 00000000..85bef3c6 --- /dev/null +++ b/android/src/main/java/com/RNRSA/CsrHelper.java @@ -0,0 +1,121 @@ +package com.RNRSA; + +import android.util.Log; + +import org.spongycastle.asn1.ASN1ObjectIdentifier; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; +import org.spongycastle.asn1.x500.X500Name; +import org.spongycastle.asn1.x509.AlgorithmIdentifier; +import org.spongycastle.asn1.x509.ExtensionsGenerator; +import org.spongycastle.operator.ContentSigner; +import org.spongycastle.operator.OperatorCreationException; +import org.spongycastle.pkcs.PKCS10CertificationRequest; +import org.spongycastle.pkcs.PKCS10CertificationRequestBuilder; +import org.spongycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.util.HashMap; +import java.util.Map; + +public class CsrHelper { + + private final static String DEFAULT_SIGNATURE_ALGORITHM = "SHA256withECDSA"; + private final static String CN_PATTERN = "CN=%s"; + + private static class JCESigner implements ContentSigner { + + private static Map ALGOS = new HashMap(); + + static { + ALGOS.put("SHA256withECDSA".toLowerCase(), new AlgorithmIdentifier( + new ASN1ObjectIdentifier("1.2.840.10045.4.3.2"))); +// ALGOS.put("SHA256withRSA".toLowerCase(), new AlgorithmIdentifier( +// new ASN1ObjectIdentifier("1.2.840.113549.1.1.11"))); +// ALGOS.put("SHA1withRSA".toLowerCase(), new AlgorithmIdentifier( +// new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"))); + + } + + private String mAlgo; + private Signature signature; + private ByteArrayOutputStream outputStream; + + public JCESigner( String sigAlgo, String keyTag) { + mAlgo = sigAlgo.toLowerCase(); + try { + KeyStore.Entry entry = getEntry(keyTag); + this.outputStream = new ByteArrayOutputStream(); + this.signature = Signature.getInstance(sigAlgo); + PrivateKey key = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey(); + this.signature.initSign(key); + } catch (GeneralSecurityException gse) { + Log.e("generateCSR", "generateCSR: " + gse.getMessage()); + throw new IllegalArgumentException(gse.getMessage()); + } + catch (IOException gse) { + Log.e("generateCSR", "IOException: " + gse.getMessage()); + throw new IllegalArgumentException(gse.getMessage()); + } + } + + public KeyStore.Entry getEntry (String keyTag) throws GeneralSecurityException, IOException { + + + KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); + ks.load(null); + return ks.getEntry(keyTag, null); + } + + @Override + public AlgorithmIdentifier getAlgorithmIdentifier() { + AlgorithmIdentifier id = ALGOS.get(mAlgo); + if (id == null) { + throw new IllegalArgumentException("Does not support algo: " + + mAlgo); + } + return id; + } + + @Override + public OutputStream getOutputStream() { + return outputStream; + } + + @Override + public byte[] getSignature() { + try { + signature.update(outputStream.toByteArray()); + return signature.sign(); + } catch (GeneralSecurityException gse) { + gse.printStackTrace(); + return null; + } + } + } + + //Create the certificate signing request (CSR) from private and public keys + public static PKCS10CertificationRequest generateCSR(PublicKey publicKey, String cn, String keyTag) throws IOException, + OperatorCreationException { + + String principal = String.format(CN_PATTERN, cn); + ContentSigner signer = new JCESigner (DEFAULT_SIGNATURE_ALGORITHM, keyTag); + PKCS10CertificationRequestBuilder csrBuilder = new JcaPKCS10CertificationRequestBuilder( + new X500Name(principal), publicKey); + + ExtensionsGenerator extensionsGenerator = new ExtensionsGenerator(); +// extensionsGenerator.addExtension(Extension.basicConstraints, true, new BasicConstraints( +// true)); + csrBuilder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest, + extensionsGenerator.generate()); + PKCS10CertificationRequest csr = csrBuilder.build(signer); + return csr; + } +} + diff --git a/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java b/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java index 3aad603d..c5928c5d 100644 --- a/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java +++ b/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java @@ -68,6 +68,29 @@ public void run() { }); } + @ReactMethod + public void generateCSRWithEC(final String cn,final String keyTag, final int keySize, final Promise promise) { + final ReactApplicationContext reactContext = this.reactContext; + + AsyncTask.execute(new Runnable() { + @Override + public void run() { + WritableNativeMap keys = new WritableNativeMap(); + + try { + RSA rsa = new RSA(); + rsa.generateCSR(cn,keyTag, keySize, reactContext); + keys.putString("csr", rsa.getCSR()); + promise.resolve(keys); + } catch (NoSuchAlgorithmException e) { + promise.reject("Error", e.getMessage()); + } catch (Exception e) { + promise.reject("Error", e.getMessage()); + } + } + }); + } + @ReactMethod public void deletePrivateKey(final String keyTag, final Promise promise) { AsyncTask.execute(new Runnable() { diff --git a/android/src/main/java/com/RNRSA/RSA.java b/android/src/main/java/com/RNRSA/RSA.java index b6fa52ce..97434970 100644 --- a/android/src/main/java/com/RNRSA/RSA.java +++ b/android/src/main/java/com/RNRSA/RSA.java @@ -9,6 +9,9 @@ import android.util.Base64; import android.content.Context; + +import java.security.SecureRandom; +import java.security.spec.ECGenParameterSpec; import java.util.Calendar; import java.math.BigInteger; import java.io.Reader; @@ -37,19 +40,23 @@ import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.BadPaddingException; -import javax.security.cert.X509Certificate; import javax.security.auth.x500.X500Principal; import java.io.IOException; + + import org.spongycastle.asn1.ASN1InputStream; import org.spongycastle.asn1.ASN1Encodable; +import org.spongycastle.asn1.ASN1ObjectIdentifier; import org.spongycastle.asn1.ASN1Primitive; +import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.spongycastle.asn1.pkcs.PrivateKeyInfo; import org.spongycastle.asn1.pkcs.RSAPublicKey; import org.spongycastle.asn1.pkcs.RSAPrivateKey; import org.spongycastle.asn1.x509.SubjectPublicKeyInfo; -import org.spongycastle.asn1.x509.RSAPublicKeyStructure; +import org.spongycastle.operator.OperatorCreationException; +import org.spongycastle.pkcs.PKCS10CertificationRequest; import org.spongycastle.util.io.pem.PemObject; import org.spongycastle.util.io.pem.PemWriter; import org.spongycastle.util.io.pem.PemReader; @@ -57,11 +64,13 @@ import org.spongycastle.openssl.PEMParser; import org.spongycastle.util.io.pem.PemObject; + import static android.security.keystore.KeyProperties.*; import static java.nio.charset.StandardCharsets.UTF_8; import java.nio.charset.Charset; + public class RSA { public static Charset CharsetUTF_8; @@ -69,11 +78,13 @@ public class RSA { private static final String PUBLIC_HEADER = "RSA PUBLIC KEY"; private static final String PRIVATE_HEADER = "RSA PRIVATE KEY"; + private static final String CSR_HEADER = "CERTIFICATE REQUEST"; private String keyTag; private PublicKey publicKey; private PrivateKey privateKey; + private PKCS10CertificationRequest csr; public RSA() { this.setupCharset(); @@ -328,6 +339,56 @@ public void generate(String keyTag, int keySize, Context context) throws IOExcep KeyPair keyPair = kpg.genKeyPair(); this.publicKey = keyPair.getPublic(); + + } + + @TargetApi(18) + public void generateCSR(String cn,String keyTag, int keySize, Context context) throws IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException { + + KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); + if (android.os.Build.VERSION.SDK_INT >= 23) { + + kpg.initialize(new KeyGenParameterSpec.Builder( + keyTag, + KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) + .setDigests(KeyProperties.DIGEST_SHA256, + KeyProperties.DIGEST_SHA512, + KeyProperties.DIGEST_NONE) + .setKeySize(keySize) + .build()); + } else { + Calendar endDate = Calendar.getInstance(); + endDate.add(Calendar.YEAR, 1); + KeyPairGeneratorSpec.Builder keyPairGeneratorSpec = new KeyPairGeneratorSpec.Builder(context) + .setAlias(keyTag) + .setSubject(new X500Principal( + String.format("CN=%s", keyTag, context.getPackageName()) + )) + .setSerialNumber(BigInteger.ONE) + .setStartDate(Calendar.getInstance().getTime()) + .setEndDate(endDate.getTime()); + if (android.os.Build.VERSION.SDK_INT >= 19) { + keyPairGeneratorSpec.setKeySize(keySize).setKeyType(KeyProperties.KEY_ALGORITHM_EC); + } + kpg.initialize(keyPairGeneratorSpec.build()); + } + + + KeyPair keyPair = kpg.genKeyPair(); + this.publicKey = keyPair.getPublic(); + + try { + this.csr = CsrHelper.generateCSR(this.publicKey, cn, keyTag); + } catch (OperatorCreationException e) { + e.printStackTrace(); + } + } + + + public String getCSR() throws IOException { + byte CSRder[] = this.csr.getEncoded(); + return dataToPem(CSR_HEADER, CSRder); } } + diff --git a/index.d.ts b/index.d.ts index cf31eb5e..60cb17b3 100644 --- a/index.d.ts +++ b/index.d.ts @@ -22,6 +22,7 @@ declare module 'react-native-rsa-native' { namespace RSAKeychain { export function generate(keyTag: string, keySize: number): Promise; export function generateKeys(keyTag: string, keySize: number): Promise; + export function generateCSRWithEC(cn: String,keyTag: string, keySize: number): Promise; export function deletePrivateKey(keyTag: string): Promise; export function encrypt(data: string, keyTag: string): Promise; export function decrypt(data: string, keyTag: string): Promise; From 9386b5e196f4b4b5264ccf15c4842ce2d37550f5 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Mon, 9 Dec 2019 11:16:07 +0330 Subject: [PATCH 02/13] Add getPublicKey from generate CSR --- android/src/main/java/com/RNRSA/RNRSAKeychainModule.java | 1 + index.d.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java b/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java index c5928c5d..5a2d0288 100644 --- a/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java +++ b/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java @@ -81,6 +81,7 @@ public void run() { RSA rsa = new RSA(); rsa.generateCSR(cn,keyTag, keySize, reactContext); keys.putString("csr", rsa.getCSR()); + keys.putString("public", rsa.getPublicKey()); promise.resolve(keys); } catch (NoSuchAlgorithmException e) { promise.reject("Error", e.getMessage()); diff --git a/index.d.ts b/index.d.ts index 60cb17b3..12060168 100644 --- a/index.d.ts +++ b/index.d.ts @@ -3,6 +3,10 @@ declare module 'react-native-rsa-native' { public: string; } + interface CSRKey { + csr: string; + } + interface KeyPair extends PublicKey { private: string; } @@ -22,7 +26,7 @@ declare module 'react-native-rsa-native' { namespace RSAKeychain { export function generate(keyTag: string, keySize: number): Promise; export function generateKeys(keyTag: string, keySize: number): Promise; - export function generateCSRWithEC(cn: String,keyTag: string, keySize: number): Promise; + export function generateCSRWithEC(cn: String,keyTag: string, keySize: number): Promise; export function deletePrivateKey(keyTag: string): Promise; export function encrypt(data: string, keyTag: string): Promise; export function decrypt(data: string, keyTag: string): Promise; From bf85d1345336505e3657c3e08d30c3a5566c146e Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Sat, 14 Dec 2019 09:41:40 +0330 Subject: [PATCH 03/13] Add SHA1withRSA for RSA --- android/src/main/java/com/RNRSA/RNRSAKeychainModule.java | 2 ++ android/src/main/java/com/RNRSA/RSA.java | 2 +- index.d.ts | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java b/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java index 5a2d0288..a9caf37f 100644 --- a/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java +++ b/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java @@ -19,6 +19,7 @@ public class RNRSAKeychainModule extends ReactContextBaseJavaModule { private static final String SHA256withRSA = "SHA256withRSA"; private static final String SHA512withRSA = "SHA512withRSA"; + private static final String SHA1withRSA = "SHA1withRSA"; private final ReactApplicationContext reactContext; @@ -37,6 +38,7 @@ public Map getConstants() { final Map constants = new HashMap<>(); constants.put(SHA256withRSA, SHA256withRSA); constants.put(SHA512withRSA, SHA512withRSA); + constants.put(SHA1withRSA, SHA1withRSA); return constants; } diff --git a/android/src/main/java/com/RNRSA/RSA.java b/android/src/main/java/com/RNRSA/RSA.java index 97434970..04a40dd6 100644 --- a/android/src/main/java/com/RNRSA/RSA.java +++ b/android/src/main/java/com/RNRSA/RSA.java @@ -315,7 +315,7 @@ public void generate(String keyTag, int keySize, Context context) throws IOExcep PURPOSE_ENCRYPT | PURPOSE_DECRYPT | PURPOSE_SIGN | PURPOSE_VERIFY ) .setKeySize(keySize) - .setDigests(DIGEST_SHA256, DIGEST_SHA512) + .setDigests(DIGEST_SHA256, DIGEST_SHA512, DIGEST_SHA1) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) .setSignaturePaddings(KeyProperties.SIGNATURE_PADDING_RSA_PKCS1) .build() diff --git a/index.d.ts b/index.d.ts index 12060168..323b6826 100644 --- a/index.d.ts +++ b/index.d.ts @@ -31,7 +31,7 @@ declare module 'react-native-rsa-native' { export function encrypt(data: string, keyTag: string): Promise; export function decrypt(data: string, keyTag: string): Promise; export function sign(data: string, keyTag: string): Promise; - export function signWithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA'): Promise; + export function signWithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; export function verify(data: string, secretToVerify: string, keyTag: string): Promise; export function getPublicKey(keyTag: string): Promise; export const SHA256withRSA: string; From c6886c666572091d18656460cd2b86c250474e78 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Sat, 14 Dec 2019 10:13:55 +0330 Subject: [PATCH 04/13] add verifyWithAlgorithm in RSAKeychain types --- index.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/index.d.ts b/index.d.ts index 323b6826..9c7a3dfa 100644 --- a/index.d.ts +++ b/index.d.ts @@ -33,6 +33,7 @@ declare module 'react-native-rsa-native' { export function sign(data: string, keyTag: string): Promise; export function signWithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; export function verify(data: string, secretToVerify: string, keyTag: string): Promise; + export function verifyWithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; export function getPublicKey(keyTag: string): Promise; export const SHA256withRSA: string; export const SHA512withRSA: string; From d1b0fa6270601889e9bc9f41d88a8fbc218484e9 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Mon, 23 Dec 2019 18:48:28 +0330 Subject: [PATCH 05/13] Add singWithBase64 & Fix dateToPem for publicKey --- .../src/main/java/com/RNRSA/RNRSAKeychainModule.java | 1 - android/src/main/java/com/RNRSA/RSA.java | 12 ++++++------ index.d.ts | 2 ++ 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java b/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java index a9caf37f..e8df88d8 100644 --- a/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java +++ b/android/src/main/java/com/RNRSA/RNRSAKeychainModule.java @@ -83,7 +83,6 @@ public void run() { RSA rsa = new RSA(); rsa.generateCSR(cn,keyTag, keySize, reactContext); keys.putString("csr", rsa.getCSR()); - keys.putString("public", rsa.getPublicKey()); promise.resolve(keys); } catch (NoSuchAlgorithmException e) { promise.reject("Error", e.getMessage()); diff --git a/android/src/main/java/com/RNRSA/RSA.java b/android/src/main/java/com/RNRSA/RSA.java index 04a40dd6..b98e30b7 100644 --- a/android/src/main/java/com/RNRSA/RSA.java +++ b/android/src/main/java/com/RNRSA/RSA.java @@ -105,14 +105,13 @@ private void setupCharset() { } public String getPublicKey() throws IOException { - byte[] pkcs1PublicKey = publicKeyToPkcs1(this.publicKey); - - return dataToPem(PUBLIC_HEADER, pkcs1PublicKey); +// byte[] pkcs1PublicKey = publicKeyToPkcs1(this.publicKey); +// return dataToPem(PUBLIC_HEADER, pkcs1PublicKey); + return Base64.encodeToString(this.publicKey.getEncoded(), Base64.DEFAULT); } public String getPrivateKey() throws IOException { byte[] pkcs1PrivateKey = privateKeyToPkcs1(this.privateKey); - return dataToPem(PRIVATE_HEADER, pkcs1PrivateKey); } @@ -343,8 +342,8 @@ public void generate(String keyTag, int keySize, Context context) throws IOExcep } @TargetApi(18) - public void generateCSR(String cn,String keyTag, int keySize, Context context) throws IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException { - + public void generateCSR(String cn,String keyTag, int keySize, Context context) throws IOException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException, UnrecoverableEntryException, KeyStoreException, CertificateException { + this.deletePrivateKey(); KeyPairGenerator kpg = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_EC, "AndroidKeyStore"); if (android.os.Build.VERSION.SDK_INT >= 23) { @@ -355,6 +354,7 @@ public void generateCSR(String cn,String keyTag, int keySize, Context context) t KeyProperties.DIGEST_SHA512, KeyProperties.DIGEST_NONE) .setKeySize(keySize) + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .build()); } else { Calendar endDate = Calendar.getInstance(); diff --git a/index.d.ts b/index.d.ts index 9c7a3dfa..ddd862f6 100644 --- a/index.d.ts +++ b/index.d.ts @@ -32,8 +32,10 @@ declare module 'react-native-rsa-native' { export function decrypt(data: string, keyTag: string): Promise; export function sign(data: string, keyTag: string): Promise; export function signWithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; + export function sign64WithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; export function verify(data: string, secretToVerify: string, keyTag: string): Promise; export function verifyWithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; + export function verify64WithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; export function getPublicKey(keyTag: string): Promise; export const SHA256withRSA: string; export const SHA512withRSA: string; From 1ae0bf995abbd3680a159d65e8f442b8357fc211 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Sat, 11 Jan 2020 17:08:45 +0330 Subject: [PATCH 06/13] Fix DIGEST SHA384 --- android/src/main/java/com/RNRSA/CsrHelper.java | 8 ++++---- android/src/main/java/com/RNRSA/RSA.java | 5 +++++ index.d.ts | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/android/src/main/java/com/RNRSA/CsrHelper.java b/android/src/main/java/com/RNRSA/CsrHelper.java index 85bef3c6..dc96e81a 100644 --- a/android/src/main/java/com/RNRSA/CsrHelper.java +++ b/android/src/main/java/com/RNRSA/CsrHelper.java @@ -36,10 +36,10 @@ private static class JCESigner implements ContentSigner { static { ALGOS.put("SHA256withECDSA".toLowerCase(), new AlgorithmIdentifier( new ASN1ObjectIdentifier("1.2.840.10045.4.3.2"))); -// ALGOS.put("SHA256withRSA".toLowerCase(), new AlgorithmIdentifier( -// new ASN1ObjectIdentifier("1.2.840.113549.1.1.11"))); -// ALGOS.put("SHA1withRSA".toLowerCase(), new AlgorithmIdentifier( -// new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"))); + ALGOS.put("SHA256withRSA".toLowerCase(), new AlgorithmIdentifier( + new ASN1ObjectIdentifier("1.2.840.113549.1.1.11"))); + ALGOS.put("SHA1withRSA".toLowerCase(), new AlgorithmIdentifier( + new ASN1ObjectIdentifier("1.2.840.113549.1.1.5"))); } diff --git a/android/src/main/java/com/RNRSA/RSA.java b/android/src/main/java/com/RNRSA/RSA.java index b98e30b7..3395bd16 100644 --- a/android/src/main/java/com/RNRSA/RSA.java +++ b/android/src/main/java/com/RNRSA/RSA.java @@ -10,6 +10,7 @@ import android.content.Context; +import java.security.MessageDigest; import java.security.SecureRandom; import java.security.spec.ECGenParameterSpec; import java.util.Calendar; @@ -171,6 +172,7 @@ public String decrypt64(String b64message) throws NoSuchAlgorithmException, Inva } private String sign(byte[] messageBytes, String algorithm) throws NoSuchAlgorithmException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, InvalidKeyException, SignatureException { + Signature privateSignature = Signature.getInstance(algorithm); privateSignature.initSign(this.privateKey); privateSignature.update(messageBytes); @@ -184,6 +186,7 @@ public String sign64(String b64message, String algorithm) throws NoSuchAlgorithm return sign(messageBytes, algorithm); } + //utf-8 message public String sign(String message, String signature) throws NoSuchAlgorithmException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException, InvalidKeyException, SignatureException { byte[] messageBytes = message.getBytes(CharsetUTF_8); @@ -352,8 +355,10 @@ public void generateCSR(String cn,String keyTag, int keySize, Context context) t KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY) .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512, + DIGEST_SHA384, KeyProperties.DIGEST_NONE) .setKeySize(keySize) + .setAlgorithmParameterSpec(new ECGenParameterSpec("secp256r1")) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .build()); } else { diff --git a/index.d.ts b/index.d.ts index ddd862f6..62d3f67a 100644 --- a/index.d.ts +++ b/index.d.ts @@ -31,8 +31,8 @@ declare module 'react-native-rsa-native' { export function encrypt(data: string, keyTag: string): Promise; export function decrypt(data: string, keyTag: string): Promise; export function sign(data: string, keyTag: string): Promise; - export function signWithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; - export function sign64WithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; + export function signWithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA' | 'SHA256withECDSA'): Promise; + export function sign64WithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA' | 'SHA256withECDSA'): Promise; export function verify(data: string, secretToVerify: string, keyTag: string): Promise; export function verifyWithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; export function verify64WithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; From 31df05f2efdf0ea1585372005b57a8886380be89 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Mon, 20 Jan 2020 18:00:27 +0330 Subject: [PATCH 07/13] Rewrite iOS with swift --- .../org.eclipse.buildship.core.prefs | 2 + .../org.eclipse.buildship.core.prefs | 2 + index.d.ts | 34 +- ios/CSRSwift.swift | 472 ++++++++++++++ ios/CSRSwiftConstants.swift | 185 ++++++ ios/RNRSA-Bridging-Header.h | 6 + ios/RNRSA.h | 16 - ios/RNRSA.m | 267 +------- ios/RNRSA.swift | 168 +++++ ios/RNRSA.xcodeproj/project.pbxproj | 70 +- ios/RNRSAKeychain.m | 55 ++ ios/RNRSAKeychain.swift | 225 +++++++ ios/RSAECFormatter.swift | 76 +++ ios/RSAECNative.swift | 612 ++++++++++++++++++ ios/RSAFormatter.h | 17 - ios/RSAFormatter.m | 72 --- ios/RSAKeyEncoding.swift | 85 +++ ios/RSANative.h | 42 -- ios/RSANative.m | 371 ----------- react-native-rsa-native.podspec | 4 +- 20 files changed, 1986 insertions(+), 795 deletions(-) create mode 100644 android/.settings/org.eclipse.buildship.core.prefs create mode 100644 example/android/.settings/org.eclipse.buildship.core.prefs create mode 100644 ios/CSRSwift.swift create mode 100644 ios/CSRSwiftConstants.swift create mode 100644 ios/RNRSA-Bridging-Header.h delete mode 100644 ios/RNRSA.h create mode 100644 ios/RNRSA.swift create mode 100644 ios/RNRSAKeychain.m create mode 100644 ios/RNRSAKeychain.swift create mode 100644 ios/RSAECFormatter.swift create mode 100644 ios/RSAECNative.swift delete mode 100644 ios/RSAFormatter.h delete mode 100644 ios/RSAFormatter.m create mode 100644 ios/RSAKeyEncoding.swift delete mode 100644 ios/RSANative.h delete mode 100644 ios/RSANative.m diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..e8895216 --- /dev/null +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/example/android/.settings/org.eclipse.buildship.core.prefs b/example/android/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 00000000..e8895216 --- /dev/null +++ b/example/android/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,2 @@ +connection.project.dir= +eclipse.preferences.version=1 diff --git a/index.d.ts b/index.d.ts index 62d3f67a..3216bd63 100644 --- a/index.d.ts +++ b/index.d.ts @@ -10,17 +10,34 @@ declare module 'react-native-rsa-native' { interface KeyPair extends PublicKey { private: string; } + type TypeCrypto = + 'SHA256withRSA'| + 'SHA512withRSA'| + 'SHA1withRSA'| + 'SHA256withEC'| + 'SHA512withEC'| + 'SHA1withEC' + namespace RSA { export function generate(keySize: number): Promise; export function generateKeys(keySize: number): Promise; export function encrypt(data: string, key: string): Promise; export function decrypt(data: string, key: string): Promise; + export function encrypt64(data: string, key: string): Promise; + export function decrypt64(data: string, key: string): Promise; export function sign(data: string, key: string): Promise; - export function signWithAlgorithm(data: string, key: string, signature?: 'SHA256withRSA' | 'SHA512withRSA'): Promise; + export function signWithAlgorithm(data: string, key: string, signature?: TypeCrypto): Promise; + export function sign64WithAlgorithm(data: string, key: string, signature?: TypeCrypto): Promise; export function verify(data: string, secretToVerify: string, key: string): Promise; + export function verifyWithAlgorithm(data: string, secretToVerify: string, key: string, signature?: TypeCrypto): Promise; + export function verify64WithAlgorithm(data: string, secretToVerify: string, key: string, signature?: TypeCrypto): Promise; export const SHA256withRSA: string; export const SHA512withRSA: string; + export const SHA1withRSA: string; + export const SHA256withECDSA: string; + export const SHA512withECDSA: string; + export const SHA1withECDSA: string; } namespace RSAKeychain { @@ -30,15 +47,22 @@ declare module 'react-native-rsa-native' { export function deletePrivateKey(keyTag: string): Promise; export function encrypt(data: string, keyTag: string): Promise; export function decrypt(data: string, keyTag: string): Promise; + export function encrypt64(data: string, keyTag: string): Promise; + export function decrypt64(data: string, keyTag: string): Promise; export function sign(data: string, keyTag: string): Promise; - export function signWithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA' | 'SHA256withECDSA'): Promise; - export function sign64WithAlgorithm(data: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA' | 'SHA256withECDSA'): Promise; + export function signWithAlgorithm(data: string, keyTag: string, signature?: TypeCrypto): Promise; + export function sign64WithAlgorithm(data: string, keyTag: string, signature?: TypeCrypto): Promise; export function verify(data: string, secretToVerify: string, keyTag: string): Promise; - export function verifyWithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; - export function verify64WithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: 'SHA256withRSA' | 'SHA512withRSA' | 'SHA1withRSA'): Promise; + export function verifyWithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: TypeCrypto): Promise; + export function verify64WithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: TypeCrypto): Promise; export function getPublicKey(keyTag: string): Promise; + export function deletePrivateKey(keyTag: string): Promise; export const SHA256withRSA: string; export const SHA512withRSA: string; + export const SHA1withRSA: string; + export const SHA256withECDSa: string; + export const SHA512withECDSA: string; + export const SHA1withECDSA: string; } export { RSA, RSAKeychain }; diff --git a/ios/CSRSwift.swift b/ios/CSRSwift.swift new file mode 100644 index 00000000..730b4178 --- /dev/null +++ b/ios/CSRSwift.swift @@ -0,0 +1,472 @@ +// +// CertificateSigningRequest.swift +// CertificateSigningRequestSwift +// +// Created by Corey Baker on 10/19/16. +// Copyright © Corey Baker. All rights reserved. +// +// This is a port of ios-csr by Ales Teska (https://github.com/ateska/ios-csr) +// from Objective-c to Swift. Additions have been made to allow SHA256 and SHA512. +// +// Copyright (C) 2016 Corey Baker +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +/* + + Certification Request Syntax Specification: http://www.ietf.org/rfc/rfc2986.txt + + */ + +import Foundation +import CommonCrypto + +public class CertificateSigningRequest:NSObject { + private let OBJECT_commonName:[UInt8] = [0x06, 0x03, 0x55, 0x04, 0x03] + private let OBJECT_countryName:[UInt8] = [0x06, 0x03, 0x55, 0x04, 0x06] + private let OBJECT_localityName:[UInt8] = [0x06, 0x03, 0x55, 0x04, 0x07] + private let OBJECT_organizationName:[UInt8] = [0x06, 0x03, 0x55, 0x04, 0x0A] + private let OBJECT_organizationalUnitName:[UInt8] = [0x06, 0x03, 0x55, 0x04, 0x0B] + private let OBJECT_stateOrProvinceName:[UInt8] = [0x06, 0x03, 0x55, 0x04, 0x08] + private let SEQUENCE_tag:UInt8 = 0x30 + private let SET_tag:UInt8 = 0x31 + + private let commonName:String? + private let countryName:String? + private let localityName:String? + private let organizationName:String? + private let organizationUnitName:String? + private let stateOrProvinceName:String? + private var keyAlgorithm: KeyAlgorithm! + private var subjectDER:Data? + + + public init(commonName: String?, organizationName:String?, organizationUnitName:String?, countryName:String?, stateOrProvinceName:String?, localityName:String?, keyAlgorithm: KeyAlgorithm){ + + self.commonName = commonName + self.organizationName = organizationName + self.organizationUnitName = organizationUnitName + self.countryName = countryName + self.stateOrProvinceName = stateOrProvinceName + self.localityName = localityName + self.subjectDER = nil + self.keyAlgorithm = keyAlgorithm + + super.init() + } + + public convenience override init(){ + self.init(commonName: nil, organizationName:nil, organizationUnitName:nil, countryName:nil, stateOrProvinceName:nil, localityName:nil, keyAlgorithm: KeyAlgorithm.rsa(signatureType: .sha512)) + } + + public convenience init(keyAlgorithm: KeyAlgorithm){ + self.init(commonName: nil, organizationName:nil, organizationUnitName:nil, countryName:nil, stateOrProvinceName:nil, localityName:nil, keyAlgorithm: keyAlgorithm) + } + + public func build(_ publicKeyBits:Data, privateKey: SecKey) -> Data?{ + + var certificationRequestInfo = buldCertificationRequestInfo(publicKeyBits) + var certificationRequestInfoBytes = [UInt8](repeating: 0, count: certificationRequestInfo.count) + certificationRequestInfo.copyBytes(to: &certificationRequestInfoBytes, count: certificationRequestInfo.count) + let shaBytes = keyAlgorithm.sequenceObjectEncryptionType + + + var signature = [UInt8](repeating: 0, count: 256) + var signatureLen:Int = signature.count + + + if #available(iOS 11, *) { + // Build signature - step 1: SHA1 hash + // Build signature - step 2: Sign hash + var error: Unmanaged? + + if let signatureData = SecKeyCreateSignature(privateKey, keyAlgorithm.signatureAlgorithm, certificationRequestInfo as CFData, &error) as Data?{ + signatureData.copyBytes(to: &signature, count: signatureData.count) + signatureLen = signatureData.count + } + + if error != nil{ + print("Error in creating signature: \(error!.takeRetainedValue())") + } + + } else { + // Fallback on earlier versions + + // Build signature - step 1: SHA1 hash + var digest = [UInt8](repeating: 0, count: keyAlgorithm.digestLength) + let padding = keyAlgorithm.padding + + switch keyAlgorithm! { + + case .rsa(signatureType: .sha1), .ec(signatureType: .sha1): + + var SHA1 = CC_SHA1_CTX() + CC_SHA1_Init(&SHA1) + CC_SHA1_Update(&SHA1, certificationRequestInfoBytes, CC_LONG(certificationRequestInfo.count)) + + CC_SHA1_Final(&digest, &SHA1) + + case .rsa(signatureType: .sha256), .ec(signatureType: .sha256): + + var SHA256 = CC_SHA256_CTX() + CC_SHA256_Init(&SHA256) + CC_SHA256_Update(&SHA256, certificationRequestInfoBytes, CC_LONG(certificationRequestInfo.count)) + CC_SHA256_Final(&digest, &SHA256) + + case .rsa(signatureType: .sha512), .ec(signatureType: .sha512): + + var SHA512 = CC_SHA512_CTX() + CC_SHA512_Init(&SHA512) + CC_SHA512_Update(&SHA512, certificationRequestInfoBytes, CC_LONG(certificationRequestInfo.count)) + CC_SHA512_Final(&digest, &SHA512) + + /* + default: + + print("Error: signing algotirthm \(signAlgorithm) is not implemented") + return nil + */ + } + + // Build signature - step 2: Sign hash + let result = SecKeyRawSign(privateKey, padding, digest, digest.count, &signature, &signatureLen) + + if result != errSecSuccess{ + print("Error signing: \(result)") + return nil + } + + } + + + var certificationRequest = Data(capacity: 1024) + certificationRequest.append(certificationRequestInfo) + certificationRequest.append(shaBytes, count: shaBytes.count) + + var signData = Data(capacity: 257) + let zero:UInt8 = 0 // Prepend zero + signData.append(zero) + signData.append(signature, count: signatureLen) + appendBITSTRING(signData, into: &certificationRequest) + + enclose(&certificationRequest, by: SEQUENCE_tag) // Enclose into SEQUENCE + + return certificationRequest + } + + public func buildAndEncodeDataAsString(_ publicKeyBits:Data, privateKey: SecKey)-> String? { + + guard let buildData = self.build(publicKeyBits, privateKey: privateKey) else{ + return nil + } + + return buildData.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) + + } + + public func buildCSRAndReturnString(_ publicKeyBits:Data, privateKey: SecKey)-> String? { + + guard let csrString = self.buildAndEncodeDataAsString(publicKeyBits, privateKey: privateKey) else{ + return nil + } + + let head = "-----BEGIN CERTIFICATE REQUEST-----\n"; + let foot = "-----END CERTIFICATE REQUEST-----\n"; + var isMultiple = false; + var newCSRString = head; + + //Check if string size is a multiple of 64 + if (csrString.count % 64 == 0){ + isMultiple = true; + } + + for (i, char) in csrString.enumerated() { + newCSRString.append(char) + + if ((i != 0) && ((i+1) % 64 == 0)){ + newCSRString.append("\n") + } + + if ((i == csrString.count-1) && !isMultiple){ + newCSRString.append("\n") + } + + } + + newCSRString = newCSRString+foot + + return newCSRString + } + + + func buldCertificationRequestInfo(_ publicKeyBits:Data) -> Data{ + var certificationRequestInfo = Data(capacity: 256) + + //Add version + let version: [UInt8] = [0x02, 0x01, 0x00] // ASN.1 Representation of integer with value 1 + certificationRequestInfo.append(version, count: version.count) + + //Add subject + var subject = Data(capacity: 256) + if countryName != nil{ + appendSubjectItem(OBJECT_countryName, value: countryName!, into: &subject) + } + + if stateOrProvinceName != nil { + appendSubjectItem(OBJECT_stateOrProvinceName, value: stateOrProvinceName!, into: &subject) + } + + if localityName != nil { + appendSubjectItem(OBJECT_localityName, value: localityName!, into: &subject) + } + + if organizationName != nil{ + appendSubjectItem(OBJECT_organizationName, value: organizationName!, into: &subject) + } + + if organizationUnitName != nil { + appendSubjectItem(OBJECT_organizationalUnitName, value: organizationUnitName!, into: &subject) + } + + if commonName != nil{ + appendSubjectItem(OBJECT_commonName, value: commonName!, into: &subject) + } + + enclose(&subject, by: SEQUENCE_tag)// Enclose into SEQUENCE + + subjectDER = subject + + certificationRequestInfo.append(subject) + + //Add public key info + let publicKeyInfo = buildPublicKeyInfo(publicKeyBits) + certificationRequestInfo.append(publicKeyInfo) + + // Add attributes + let attributes:[UInt8] = [0xA0, 0x00] + certificationRequestInfo.append(attributes, count: attributes.count) + + enclose(&certificationRequestInfo, by: SEQUENCE_tag) // Enclose into SEQUENCE + + return certificationRequestInfo + } + + // Utility class methods ... + func buildPublicKeyInfo(_ publicKeyBits:Data)-> Data{ + + var publicKeyInfo = Data(capacity: 390) + + switch keyAlgorithm! { + case .rsa: + publicKeyInfo.append(OBJECT_rsaEncryptionNULL, count: OBJECT_rsaEncryptionNULL.count) + case .ec: + publicKeyInfo.append(OBJECT_ecPubicKey, count: OBJECT_ecPubicKey.count) + publicKeyInfo.append(OBJECT_ecEncryptionNULL, count: OBJECT_ecEncryptionNULL.count) + } + + enclose(&publicKeyInfo, by: SEQUENCE_tag) // Enclose into SEQUENCE + + var publicKeyASN = Data(capacity: 260) + switch keyAlgorithm! { + case .ec: + let key = getPublicKey(publicKeyBits) + publicKeyASN.append(key) + + default: + + let mod = getPublicKeyMod(publicKeyBits) + let integer:UInt8 = 0x02 //Integer + publicKeyASN.append(integer) + appendDERLength(mod.count, into: &publicKeyASN) + publicKeyASN.append(mod) + + let exp = getPublicKeyExp(publicKeyBits) + publicKeyASN.append(integer) + appendDERLength(exp.count, into: &publicKeyASN) + publicKeyASN.append(exp) + + enclose(&publicKeyASN, by: SEQUENCE_tag)// Enclose into ?? + } + + prependByte(0x00, into: &publicKeyASN) //Prepend 0 (?) + appendBITSTRING(publicKeyASN, into: &publicKeyInfo) + + enclose(&publicKeyInfo, by: SEQUENCE_tag) // Enclose into SEQUENCE + + return publicKeyInfo + } + + func appendSubjectItem(_ what:[UInt8], value: String, into: inout Data ) ->(){ + + if what.count != 5{ + print("Error: attempting to a non-subject item") + return + } + + var subjectItem = Data(capacity: 128) + + subjectItem.append(what, count: what.count) + appendUTF8String(string: value, into: &subjectItem) + enclose(&subjectItem, by: SEQUENCE_tag) + enclose(&subjectItem, by: SET_tag) + + into.append(subjectItem) + } + + func appendUTF8String(string: String, into: inout Data) ->(){ + + let strType:UInt8 = 0x0C //UTF8STRING + + into.append(strType) + appendDERLength(string.lengthOfBytes(using: String.Encoding.utf8), into: &into) + into.append(string.data(using: String.Encoding.utf8)!) + } + + func appendDERLength(_ length: Int, into: inout Data){ + + assert(length < 0x8000) + + if length < 128{ + let d = UInt8(length) + into.append(d) + + }else if (length < 0x100){ + + var d: [UInt8] = [0x81, UInt8(length & 0xFF)] + into.append(&d, count: d.count) + + }else if length < 0x8000{ + + let preRes:UInt = UInt(length & 0xFF00) + let res = UInt8(preRes >> 8) + var d: [UInt8] = [0x82, res, UInt8(length & 0xFF)] + into.append(&d, count: d.count) + } + } + + func appendBITSTRING(_ data: Data, into: inout Data)->(){ + + let strType:UInt8 = 0x03 //BIT STRING + into.append(strType) + appendDERLength(data.count, into: &into) + into.append(data) + } + + func enclose(_ data: inout Data, by: UInt8){ + + var newData = Data(capacity: data.count + 4) + + newData.append(by) + appendDERLength(data.count, into: &newData) + newData.append(data) + + data = newData + } + + func prependByte(_ byte: UInt8, into: inout Data)->(){ + + var newData = Data(capacity: into.count + 1) + + newData.append(byte) + newData.append(into) + + into = newData + } + + func getPublicKey(_ publicKeyBits:Data)->Data{ + + //Current only supports uncompressed keys, 65=1+32+32 + var iterator = 0 + + _ = derEncodingSpecificSize(publicKeyBits, at: &iterator, numOfBytes: 8) + + let range:Range = 0 ..< 65 + + return publicKeyBits.subdata(in: range) + } + + // From http://stackoverflow.com/questions/3840005/how-to-find-out-the-modulus-and-exponent-of-rsa-public-key-on-iphone-objective-c + + func getPublicKeyExp(_ publicKeyBits:Data)->Data{ + + var iterator = 0 + + iterator+=1 // TYPE - bit stream - mod + exp + _ = derEncodingGetSizeFrom(publicKeyBits, at: &iterator) // Total size + + iterator+=1 // TYPE - bit stream mod + let modSize = derEncodingGetSizeFrom(publicKeyBits, at: &iterator) + iterator += modSize + + iterator+=1 // TYPE - bit stream exp + let expSize = derEncodingGetSizeFrom(publicKeyBits, at: &iterator) + + let range:Range = iterator ..< (iterator + expSize) + + return publicKeyBits.subdata(in: range) + } + + func getPublicKeyMod(_ publicKeyBits: Data)->Data{ + + var iterator = 0 + + iterator+=1 // TYPE - bit stream - mod + exp + _ = derEncodingGetSizeFrom(publicKeyBits, at: &iterator) + + iterator+=1 // TYPE - bit stream mod + let modSize = derEncodingGetSizeFrom(publicKeyBits, at: &iterator) + + let range:Range = iterator ..< (iterator + modSize) + + return publicKeyBits.subdata(in: range) + } + + func derEncodingSpecificSize(_ buf: Data, at iterator: inout Int, numOfBytes: Int)->Int{ + + var data = [UInt8](repeating: 0, count: buf.count) + buf.copyBytes(to: &data, count: buf.count) + + if data[0] != 0x04{ + print("Error, framework only supports uncompressed keys") + } + + return buf.count + } + + func derEncodingGetSizeFrom(_ buf: Data, at iterator: inout Int)->Int{ + + var data = [UInt8](repeating: 0, count: buf.count) + buf.copyBytes(to: &data, count: buf.count) + + var itr = iterator + var numOfBytes = 1 + var ret = 0 + + if data[itr] > 0x80{ + numOfBytes = Int((data[itr] - 0x80)) + itr += 1 + } + + for index in 0 ..< numOfBytes { + ret = (ret * 0x100) + Int(data[itr + index]) + } + + iterator = itr + numOfBytes + + return ret + } +} + + + diff --git a/ios/CSRSwiftConstants.swift b/ios/CSRSwiftConstants.swift new file mode 100644 index 00000000..46c26399 --- /dev/null +++ b/ios/CSRSwiftConstants.swift @@ -0,0 +1,185 @@ +// +// CertificateSigningRequestSwiftConstants.swift +// CertificateSigningRequestSwift +// +// Created by Corey Baker on 10/8/17. +// Copyright © 2017 Network Reconnaissance Lab. All rights reserved. +// + +import Foundation +import CommonCrypto + +// Use e.g., https://misc.daniel-marschall.de/asn.1/oid-converter/online.php to convert OID (OBJECT IDENTIFIER) to ASN.1 DER hex forms +//Guide to translate OID's to bytes for ANS.1 (Look at comment section on page): https://msdn.microsoft.com/en-us/library/bb540809(v=vs.85).aspx +/* RSA */ +let OBJECT_rsaEncryptionNULL:[UInt8] = [0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00] + +// See: http://oid-info.com/get/1.2.840.113549.1.1.5 +let SEQUENCE_OBJECT_sha1WithRSAEncryption:[UInt8] = [0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 1, 1, 5, 0x05, 0x00] + +// See: http://oid-info.com/get/1.2.840.113549.1.1.11 +let SEQUENCE_OBJECT_sha256WithRSAEncryption:[UInt8] = [0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 1, 1, 0x0B, 0x05, 0x00] + +// See: http://oid-info.com/get/1.2.840.113549.1.1.13 +let SEQUENCE_OBJECT_sha512WithRSAEncryption:[UInt8] = [0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 1, 1, 0x0D, 0x05, 0x00] + +/* EC */ +let OBJECT_ecEncryptionNULL:[UInt8] = [0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07] + +let OBJECT_ecPubicKey:[UInt8] = [0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01] + +let SEQUENCE_OBJECT_sha1WithECEncryption:[UInt8] = [0x30, 0x0A, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x01] + +// See: http://www.oid-info.com/get/1.2.840.10045.4.3.2 +let SEQUENCE_OBJECT_sha256WithECEncryption:[UInt8] = [0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02] + +// See: http://oid-info.com/get/1.2.840.10045.4.3.4 +let SEQUENCE_OBJECT_sha512WithECEncryption:[UInt8] = [0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x04] + +//Enums +public enum KeyAlgorithm { + case rsa(signatureType: signature), ec(signatureType: signature) + + @available(iOS 10, *) + public var secKeyAttrType: CFString { + let result: CFString + switch self { + + case .rsa: result = kSecAttrKeyTypeRSA + case .ec: result = kSecAttrKeyTypeECSECPrimeRandom + + } + return result + } + + @available(iOS, deprecated: 10.0) + public var secKeyAttrTypeiOS9: CFString { + let result: CFString + switch self { + + case .rsa: result = kSecAttrKeyTypeRSA + case .ec: result = kSecAttrKeyTypeEC + + } + return result + } + + public var availableKeySizes: [Int] { + let result: [Int] + switch self { + + case .rsa: result = [512, 1024, 2048] + case .ec: result = [256] + + } + return result + } + + public enum signature { + case sha1, sha256, sha512 + } + + public var type:String{ + let result: String + + switch self { + case .rsa(signatureType: .sha1), .rsa(signatureType: .sha256), .rsa(signatureType: .sha512): + result = "RSA" + + case .ec(signatureType: .sha1), .ec(signatureType: .sha256), .ec(signatureType: .sha512): + result = "EC" + } + + return result + } + + @available(iOS 10, *) + public var signatureAlgorithm: SecKeyAlgorithm { + let result: SecKeyAlgorithm + switch self { + case .rsa(signatureType: .sha1): + result = .rsaSignatureMessagePKCS1v15SHA1 + case .rsa(signatureType: .sha256): + result = .rsaSignatureMessagePKCS1v15SHA256 + case .rsa(signatureType: .sha512): + result = .rsaSignatureMessagePKCS1v15SHA512 + case .ec(signatureType: .sha1): + result = .ecdsaSignatureMessageX962SHA1 + case .ec(signatureType: .sha256): + result = .ecdsaSignatureMessageX962SHA256 + case .ec(signatureType: .sha512): + result = .ecdsaSignatureMessageX962SHA512 + } + return result + + } + + @available(iOS, deprecated: 10.0) + public var digestLength: Int { + let result: Int32 + switch self { + //case .rsa(signatureType: .md5), .ec(signatureType: .md5): result = CC_MD5_DIGEST_LENGTH + case .rsa(signatureType: .sha1), .ec(signatureType: .sha1): result = CC_SHA1_DIGEST_LENGTH + //case .rsa(signatureType: .sha224), .ec(signatureType: .sha224): result = CC_SHA224_DIGEST_LENGTH + case .rsa(signatureType: .sha256), .ec(signatureType: .sha256): result = CC_SHA256_DIGEST_LENGTH + //case .rsa(signatureType: .sha384), .ec(signatureType: .sha384): result = CC_SHA384_DIGEST_LENGTH + case .rsa(signatureType: .sha512), .ec(signatureType: .sha512): result = CC_SHA512_DIGEST_LENGTH + } + return Int(result) + } + + @available(iOS, deprecated: 10.0) + public var padding: SecPadding { + let result: SecPadding + + switch self { + case .rsa(signatureType: .sha1), .ec(signatureType: .sha1): + result = SecPadding.PKCS1SHA1 + case .rsa(signatureType: .sha256), .ec(signatureType: .sha256): + result = SecPadding.PKCS1SHA256 + case .rsa(signatureType: .sha512), .ec(signatureType: .sha512): + result = SecPadding.PKCS1SHA512 + } + + return result + } + + var sequenceObjectEncryptionType: [UInt8]{ + let result:[UInt8] + switch self { + case .rsa(signatureType: .sha1): + result = SEQUENCE_OBJECT_sha1WithRSAEncryption + case .rsa(signatureType: .sha256): + result = SEQUENCE_OBJECT_sha256WithRSAEncryption + case .rsa(signatureType: .sha512): + result = SEQUENCE_OBJECT_sha512WithRSAEncryption + case .ec(signatureType: .sha1): + result = SEQUENCE_OBJECT_sha1WithECEncryption + case .ec(signatureType: .sha256): + result = SEQUENCE_OBJECT_sha256WithECEncryption + case .ec(signatureType: .sha512): + result = SEQUENCE_OBJECT_sha512WithECEncryption + } + + return result + } + + var objectEncryptionKeyType: [UInt8]{ + let result:[UInt8] + switch self { + case .rsa(signatureType: .sha1), .rsa(signatureType: .sha256), .rsa(signatureType: .sha512): + + result = OBJECT_rsaEncryptionNULL + + case .ec(signatureType: .sha1), .ec(signatureType: .sha256), .ec(signatureType: .sha512): + result = OBJECT_ecEncryptionNULL + + } + + return result + } + +} + + + diff --git a/ios/RNRSA-Bridging-Header.h b/ios/RNRSA-Bridging-Header.h new file mode 100644 index 00000000..d0ee44ec --- /dev/null +++ b/ios/RNRSA-Bridging-Header.h @@ -0,0 +1,6 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// +#import "RCTBridgeModule.h" + + diff --git a/ios/RNRSA.h b/ios/RNRSA.h deleted file mode 100644 index e9da574f..00000000 --- a/ios/RNRSA.h +++ /dev/null @@ -1,16 +0,0 @@ - -#if __has_include("RCTBridgeModule.h") -#import "RCTBridgeModule.h" -#else -#import -#endif - -@import Foundation; - -@interface RNRSA : NSObject - -@end - -@interface RNRSAKeychain : NSObject - -@end diff --git a/ios/RNRSA.m b/ios/RNRSA.m index 88dfef23..86303edf 100644 --- a/ios/RNRSA.m +++ b/ios/RNRSA.m @@ -1,275 +1,46 @@ -#import "RNRSA.h" -#import "RSANative.h" -@implementation RNRSA +// +// RNECRSASwift.m +// RNECRSA +// +// Created by saeed kargosha . +// Copyright © 1398 saeed kargosha. All rights reserved. +// -- (dispatch_queue_t)methodQueue { - return dispatch_get_main_queue(); -} +#import -+ (BOOL)requiresMainQueueSetup -{ - return NO; -} +@interface RCT_EXTERN_MODULE(RNRSA, NSObject) -RCT_EXPORT_MODULE() +RCT_EXTERN_METHOD(generate:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -- (NSDictionary *)constantsToExport -{ - return @{ - @"SHA256withRSA": @"SHA256withRSA", - @"SHA512withRSA": @"SHA512withRSA" - }; -} -// Key based API, provide the public or private key with each call - pending discussions with @amitaymolko +RCT_EXTERN_METHOD(generateKeys:(int)keySize resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXPORT_METHOD(generate:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - [self generateKeys:2048 resolve:resolve rejecter:reject]; -} -RCT_EXPORT_METHOD(generateKeys:(int)keySize resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - [rsa generate:keySize]; - NSDictionary *keys = @{ - @"private" : [rsa encodedPrivateKey], - @"public" : [rsa encodedPublicKey] - }; - resolve(keys); - }); -} -RCT_EXPORT_METHOD(encrypt:(NSString *)message withKey:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.publicKey = key; - NSString *encodedMessage = [rsa encrypt:message]; - resolve(encodedMessage); - }); -} +RCT_EXTERN_METHOD(signWithAlgorithm:(NSString *)message withKey:(NSString *)withKey withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXPORT_METHOD(decrypt:(NSString *)encodedMessage withKey:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.privateKey = key; - NSString *message = [rsa decrypt:encodedMessage]; - resolve(message); - }); -} +RCT_EXTERN_METHOD(sign64WithAlgorithm:(NSString *)message withKey:(NSString *)withKey withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXPORT_METHOD(encrypt64:(NSString *)message withKey:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.publicKey = key; - NSString *encodedMessage = [rsa encrypt64:message]; - resolve(encodedMessage); - }); -} -RCT_EXPORT_METHOD(decrypt64:(NSString *)encodedMessage withKey:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.privateKey = key; - NSString *message = [rsa decrypt64:encodedMessage]; - resolve(message); - }); -} +RCT_EXTERN_METHOD(verifyWithAlgorithm:(NSString *)signature withMessage:(NSString *)withMessage withKey:(NSString *)withKey withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXPORT_METHOD(sign:(NSString *)message withKey:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.privateKey = key; - NSString *signature = [rsa sign:message withAlgorithm: @"SHA512withRSA" withEncodeOption: NSDataBase64Encoding64CharacterLineLength]; - resolve(signature); - }); -} +RCT_EXTERN_METHOD(verify64WithAlgorithm:(NSString *)signature withMessage:(NSString *)withMessage withKey:(NSString *)withKey withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXPORT_METHOD(signWithAlgorithm:(NSString *)message withKey:(NSString *)key withAlgorithm:(NSString *)algorithm resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.privateKey = key; - NSString *signature = [rsa sign:message withAlgorithm: algorithm withEncodeOption: NSDataBase64Encoding64CharacterLineLength]; - resolve(signature); - }); -} +RCT_EXTERN_METHOD(decrypt:(NSString *)message withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXPORT_METHOD(sign64:(NSString *)message withKey:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.privateKey = key; - NSString *signature = [rsa sign64:message withAlgorithm: @"SHA512withRSA"]; - resolve(signature); - }); -} +RCT_EXTERN_METHOD(encrypt:(NSString *)message withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXPORT_METHOD(sign64WithAlgorithm:(NSString *)message withKey:(NSString *)key withAlgorithm:(NSString *)algorithm resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.privateKey = key; - NSString *signature = [rsa sign64:message withAlgorithm: algorithm]; - resolve(signature); - }); -} +RCT_EXTERN_METHOD(decrypt64:(NSString *)message withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(encrypt64:(NSString *)message withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -RCT_EXPORT_METHOD(verify:(NSString *)signature withMessage:(NSString *)message andKey:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.publicKey = key; - BOOL valid = [rsa verify:signature withMessage:message withAlgorithm: @"SHA512withRSA"]; - resolve(@(valid)); - }); -} - -RCT_EXPORT_METHOD(verifyWithAlgorithm:(NSString *)signature withMessage:(NSString *)message andKey:(NSString *)key withAlgorithm:(NSString *)algorithm resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.publicKey = key; - BOOL valid = [rsa verify:signature withMessage:message withAlgorithm: algorithm]; - resolve(@(valid)); - }); -} - -RCT_EXPORT_METHOD(verify64:(NSString *)signature withMessage:(NSString *)message andKey:(NSString *)key resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.publicKey = key; - BOOL valid = [rsa verify64:signature withMessage:message withAlgorithm: @"SHA512withRSA"]; - resolve(@(valid)); - }); -} - -RCT_EXPORT_METHOD(verify64WithAlgorithm:(NSString *)signature withMessage:(NSString *)message andKey:(NSString *)key withAlgorithm:(NSString *)algorithm resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] init]; - rsa.publicKey = key; - BOOL valid = [rsa verify64:signature withMessage:message withAlgorithm: algorithm]; - resolve(@(valid)); - }); -} - @end -@implementation RNRSAKeychain - -- (dispatch_queue_t)methodQueue { - return dispatch_get_main_queue(); -} - -+ (BOOL)requiresMainQueueSetup -{ - return NO; -} - -RCT_EXPORT_MODULE() - -- (NSDictionary *)constantsToExport -{ - return @{ - @"SHA256withRSA": @"SHA256withRSA", - @"SHA512withRSA": @"SHA512withRSA" - }; -} -// Keychain based API, provide a key chain tag with each call -RCT_EXPORT_METHOD(generate:(NSString *)keyTag resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - [self generateKeys:keyTag keySize:2048 resolve:resolve rejecter:reject]; -} -RCT_EXPORT_METHOD(generateKeys:(NSString *)keyTag keySize:(int)keySize resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - [rsa generate:keySize]; - NSDictionary *keys = @{@"public" : [rsa encodedPublicKey]}; - resolve(keys); - }); -} -RCT_EXPORT_METHOD(deletePrivateKey:(NSString *)keyTag resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - [rsa deletePrivateKey]; - resolve(@(YES)); -} -RCT_EXPORT_METHOD(encrypt:(NSString *)message withKeyTag:(NSString *)keyTag resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - NSString *encodedMessage = [rsa encrypt:message]; - resolve(encodedMessage); - }); -} -RCT_EXPORT_METHOD(decrypt:(NSString *)encodedMessage withKeyTag:(NSString *)keyTag resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - NSString *message = [rsa decrypt:encodedMessage]; - resolve(message); - }); -} - -RCT_EXPORT_METHOD(sign:(NSString *)message withKeyTag:(NSString *)keyTag resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - NSString *signature = [rsa sign:message withAlgorithm: @"SHA512withRSA" withEncodeOption: NSDataBase64Encoding64CharacterLineLength]; - resolve(signature); - }); -} - -RCT_EXPORT_METHOD(signWithAlgorithm:(NSString *)message withKeyTag:(NSString *)keyTag withAlgorithm:(NSString *)algorithm resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - NSString *signature = [rsa sign:message withAlgorithm: algorithm withEncodeOption: 0]; - resolve(signature); - }); -} - -RCT_EXPORT_METHOD(verify:(NSString *)signature withMessage:(NSString *)message andKeyTag:(NSString *)keyTag resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - BOOL valid = [rsa verify:signature withMessage:message withAlgorithm: @"SHA512withRSA"]; - resolve(@(valid)); - }); -} - -RCT_EXPORT_METHOD(verifyWithAlgorithm:(NSString *)signature withMessage:(NSString *)message andKeyTag:(NSString *)keyTag withAlgorithm:(NSString *)algorithm resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - BOOL valid = [rsa verify:signature withMessage:message withAlgorithm: algorithm]; - resolve(@(valid)); - }); -} - -RCT_EXPORT_METHOD(getPublicKey:(NSString *)keyTag resolve:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject) { - RSANative *rsa = [[RSANative alloc] initWithKeyTag:keyTag]; - NSString *key = [rsa encodedPublicKey]; - resolve(key); -} - -@end diff --git a/ios/RNRSA.swift b/ios/RNRSA.swift new file mode 100644 index 00000000..bca21db6 --- /dev/null +++ b/ios/RNRSA.swift @@ -0,0 +1,168 @@ +// +// RNRSASwift.swift +// test +// +// Created by saeed kargosha. +// Copyright © 1398 saeed kargosha. All rights reserved. +// + +//#if canImport(React) +//import React +//#endif +import Foundation + +@objc(RNRSA) +class RNRSA: NSObject { + + + @objc + func constantsToExport() -> [AnyHashable : Any]! { + return[ + "SHA256withRSA": "SHA256withRSA", + "SHA512withRSA": "SHA512withRSA", + "SHA1withRSA" : "SHA1withRSA", + "SHA256withECDSA" : "SHA256withECDSA", + "SHA512withECDSA" : "SHA512withECDSA", + "SHA1withECDSA" : "SHA1withECDSA" + ] + } + + + + // generate key with default keysize - RSA - DER format + @objc + func generate(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + self.generateKeys(2048, resolver: resolve, rejecter: reject) + } + + // generate key with keysize - RSA - DER format + @objc + func generateKeys(_ keySize: Int, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + let res = rsa_ec.generate(keySize: keySize) + if(res ?? false){ + let pub = rsa_ec.encodedPublicKeyDER() + let prv = rsa_ec.encodedPrivateKeyRSA() + let keys = ["public": pub, "private": prv] + resolve(keys) + return + } + resolve(false) + } + + @objc + func encrypt(_ message: String ,withKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPublicKey(publicKey: withKey) else { + resolve(false) + return + } + let msg = rsa_ec.encrypt(message: message) + resolve(msg) + } + + @objc + func decrypt(_ message: String ,withKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPrivateKey(privateKey: withKey) else { + resolve(false) + return + } + let msg = rsa_ec.decrypt(message: message) + resolve(msg) + } + + + @objc + func encrypt64(_ message: String ,withKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPublicKey(publicKey: withKey) else { + resolve(false) + return + } + let msg = rsa_ec.encrypt64(message: message) + resolve(msg) + } + + @objc + func decrypt64(_ message: String ,withKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPrivateKey(privateKey: withKey) else { + resolve(false) + return + } + let msg = rsa_ec.decrypt64(message: message) + resolve(msg) + } + + @objc + func verifyWithAlgorithm(_ signature: String, withMessage: String ,withKey: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPublicKey(publicKey: withKey) else { + resolve(false) + return + } + let signature = rsa_ec.verify(encodedSignature: signature, withMessage: withMessage, withAlgorithm: withAlgorithm) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(true) + } + } + + @objc + func verify64WithAlgorithm(_ signature: String, withMessage: String ,withKey: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPublicKey(publicKey: withKey) else { + resolve(false) + return + } + let signature = rsa_ec.verify64(encodedSignature: signature, withMessage: withMessage, withAlgorithm: withAlgorithm) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(true) + } + } + + @objc + func signWithAlgorithm(_ message: String, withKey: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPrivateKey(privateKey: withKey) else { + resolve(false) + return + } + let signature = rsa_ec.sign(message: message, withAlgorithm: withAlgorithm, withEncodeOption: NSData.Base64EncodingOptions(rawValue: 0)) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(signature) + } + } + + @objc + func sign64WithAlgorithm(_ message: String, withKey: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPrivateKey(privateKey: withKey) else { + resolve(false) + return + } + let signature = rsa_ec.sign64(b64message: message, withAlgorithm: withAlgorithm) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(signature) + } + } + +} + + + + + + + + + + diff --git a/ios/RNRSA.xcodeproj/project.pbxproj b/ios/RNRSA.xcodeproj/project.pbxproj index cee40d86..c55c3c7f 100644 --- a/ios/RNRSA.xcodeproj/project.pbxproj +++ b/ios/RNRSA.xcodeproj/project.pbxproj @@ -7,11 +7,15 @@ objects = { /* Begin PBXBuildFile section */ - 186F49E31F06836A00F71861 /* RSAFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 186F49E21F06836A00F71861 /* RSAFormatter.m */; }; - BF40FFDB1F05EC9000DC4E95 /* RNRSA.m in Sources */ = {isa = PBXBuildFile; fileRef = BF40FFD71F05EC9000DC4E95 /* RNRSA.m */; }; - BF40FFDC1F05EC9000DC4E95 /* RSANative.m in Sources */ = {isa = PBXBuildFile; fileRef = BF40FFDA1F05EC9000DC4E95 /* RSANative.m */; }; - BFCDFE2A1F694B870016F50C /* RSANative.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = BF40FFD91F05EC9000DC4E95 /* RSANative.h */; }; - BFCDFE2B1F694B890016F50C /* RSAFormatter.h in Copy Headers */ = {isa = PBXBuildFile; fileRef = 186F49E11F06836A00F71861 /* RSAFormatter.h */; }; + A055BADE23D5D02A00E2A830 /* RNRSA.m in Sources */ = {isa = PBXBuildFile; fileRef = A055BADD23D5D02A00E2A830 /* RNRSA.m */; }; + A055BAE123D5D04D00E2A830 /* RNRSA.swift in Sources */ = {isa = PBXBuildFile; fileRef = A055BAE023D5D04D00E2A830 /* RNRSA.swift */; }; + A055BAE323D5D08700E2A830 /* RNRSAKeychain.m in Sources */ = {isa = PBXBuildFile; fileRef = A055BAE223D5D08700E2A830 /* RNRSAKeychain.m */; }; + A055BAE523D5D09F00E2A830 /* RNRSAKeychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = A055BAE423D5D09F00E2A830 /* RNRSAKeychain.swift */; }; + A055BAE723D5D0BC00E2A830 /* RSAECFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A055BAE623D5D0BC00E2A830 /* RSAECFormatter.swift */; }; + A055BAE923D5D0EF00E2A830 /* RSAECNative.swift in Sources */ = {isa = PBXBuildFile; fileRef = A055BAE823D5D0EF00E2A830 /* RSAECNative.swift */; }; + A055BAEB23D5D10C00E2A830 /* RSAKeyEncoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = A055BAEA23D5D10C00E2A830 /* RSAKeyEncoding.swift */; }; + A055BAED23D5D12800E2A830 /* CSRSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = A055BAEC23D5D12800E2A830 /* CSRSwift.swift */; }; + A055BAEF23D5D14000E2A830 /* CSRSwiftConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = A055BAEE23D5D14000E2A830 /* CSRSwiftConstants.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -21,8 +25,6 @@ dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( - BFCDFE2B1F694B890016F50C /* RSAFormatter.h in Copy Headers */, - BFCDFE2A1F694B870016F50C /* RSANative.h in Copy Headers */, ); name = "Copy Headers"; runOnlyForDeploymentPostprocessing = 0; @@ -30,13 +32,17 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 186F49E11F06836A00F71861 /* RSAFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSAFormatter.h; sourceTree = ""; }; - 186F49E21F06836A00F71861 /* RSAFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSAFormatter.m; sourceTree = ""; }; + A055BADD23D5D02A00E2A830 /* RNRSA.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNRSA.m; sourceTree = ""; }; + A055BADF23D5D04C00E2A830 /* RNRSA-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RNRSA-Bridging-Header.h"; sourceTree = ""; }; + A055BAE023D5D04D00E2A830 /* RNRSA.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNRSA.swift; sourceTree = ""; }; + A055BAE223D5D08700E2A830 /* RNRSAKeychain.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNRSAKeychain.m; sourceTree = ""; }; + A055BAE423D5D09F00E2A830 /* RNRSAKeychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNRSAKeychain.swift; sourceTree = ""; }; + A055BAE623D5D0BC00E2A830 /* RSAECFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAECFormatter.swift; sourceTree = ""; }; + A055BAE823D5D0EF00E2A830 /* RSAECNative.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAECNative.swift; sourceTree = ""; }; + A055BAEA23D5D10C00E2A830 /* RSAKeyEncoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAKeyEncoding.swift; sourceTree = ""; }; + A055BAEC23D5D12800E2A830 /* CSRSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSRSwift.swift; sourceTree = ""; }; + A055BAEE23D5D14000E2A830 /* CSRSwiftConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSRSwiftConstants.swift; sourceTree = ""; }; BF40FFBD1F05EC4000DC4E95 /* libRNRSA.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNRSA.a; sourceTree = BUILT_PRODUCTS_DIR; }; - BF40FFD71F05EC9000DC4E95 /* RNRSA.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNRSA.m; sourceTree = ""; }; - BF40FFD81F05EC9000DC4E95 /* RNRSA.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNRSA.h; sourceTree = ""; }; - BF40FFD91F05EC9000DC4E95 /* RSANative.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSANative.h; sourceTree = ""; }; - BF40FFDA1F05EC9000DC4E95 /* RSANative.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSANative.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -53,13 +59,17 @@ BF40FFB41F05EC4000DC4E95 = { isa = PBXGroup; children = ( - 186F49E11F06836A00F71861 /* RSAFormatter.h */, - 186F49E21F06836A00F71861 /* RSAFormatter.m */, - BF40FFD81F05EC9000DC4E95 /* RNRSA.h */, - BF40FFD71F05EC9000DC4E95 /* RNRSA.m */, - BF40FFD91F05EC9000DC4E95 /* RSANative.h */, - BF40FFDA1F05EC9000DC4E95 /* RSANative.m */, + A055BAEE23D5D14000E2A830 /* CSRSwiftConstants.swift */, + A055BAEC23D5D12800E2A830 /* CSRSwift.swift */, + A055BAEA23D5D10C00E2A830 /* RSAKeyEncoding.swift */, + A055BAE823D5D0EF00E2A830 /* RSAECNative.swift */, + A055BAE623D5D0BC00E2A830 /* RSAECFormatter.swift */, + A055BAE423D5D09F00E2A830 /* RNRSAKeychain.swift */, + A055BAE223D5D08700E2A830 /* RNRSAKeychain.m */, + A055BAE023D5D04D00E2A830 /* RNRSA.swift */, + A055BADD23D5D02A00E2A830 /* RNRSA.m */, BF40FFBE1F05EC4000DC4E95 /* Products */, + A055BADF23D5D04C00E2A830 /* RNRSA-Bridging-Header.h */, ); sourceTree = ""; }; @@ -102,6 +112,7 @@ TargetAttributes = { BF40FFBC1F05EC4000DC4E95 = { CreatedOnToolsVersion = 9.0; + LastSwiftMigration = 1020; }; }; }; @@ -128,9 +139,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - BF40FFDB1F05EC9000DC4E95 /* RNRSA.m in Sources */, - BF40FFDC1F05EC9000DC4E95 /* RSANative.m in Sources */, - 186F49E31F06836A00F71861 /* RSAFormatter.m in Sources */, + A055BAE723D5D0BC00E2A830 /* RSAECFormatter.swift in Sources */, + A055BAE923D5D0EF00E2A830 /* RSAECNative.swift in Sources */, + A055BAEB23D5D10C00E2A830 /* RSAKeyEncoding.swift in Sources */, + A055BAE523D5D09F00E2A830 /* RNRSAKeychain.swift in Sources */, + A055BAE123D5D04D00E2A830 /* RNRSA.swift in Sources */, + A055BAE323D5D08700E2A830 /* RNRSAKeychain.m in Sources */, + A055BAED23D5D12800E2A830 /* CSRSwift.swift in Sources */, + A055BADE23D5D02A00E2A830 /* RNRSA.m in Sources */, + A055BAEF23D5D14000E2A830 /* CSRSwiftConstants.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -248,9 +265,14 @@ BF40FFC71F05EC4000DC4E95 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "RNRSA-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -258,9 +280,13 @@ BF40FFC81F05EC4000DC4E95 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + CLANG_ENABLE_MODULES = YES; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "RNRSA-Bridging-Header.h"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/ios/RNRSAKeychain.m b/ios/RNRSAKeychain.m new file mode 100644 index 00000000..14b83af5 --- /dev/null +++ b/ios/RNRSAKeychain.m @@ -0,0 +1,55 @@ +// +// RNECRSASwift.m +// RNECRSA +// +// Created by saeed kargosha on 10/21/1398 AP. +// Copyright © 1398 saeed kargosha. All rights reserved. +// + +#import + +@interface RCT_EXTERN_MODULE(RNRSAKeychain, NSObject) + +RCT_EXTERN_METHOD(generate:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(generateKeys:(NSString *)keyTag keySize:(int)keySize resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(generateCSR:(NSString *)keyTag CN:(NSString *)CN withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(generateCSRWithEC:(NSString *)CN keyTag:(NSString *)keyTag keySize:(int)keySize resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(generateEC:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(signWithAlgorithm:(NSString *)message keyTag:(NSString *)keyTag withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(sign64WithAlgorithm:(NSString *)message keyTag:(NSString *)keyTag withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(getPublicKeyDER:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(getPublicKeyRSA:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(getPublicKey:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(verifyWithAlgorithm:(NSString *)signature withMessage:(NSString *)withMessage keyTag:(NSString *)keyTag withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(verify64WithAlgorithm:(NSString *)signature withMessage:(NSString *)withMessage keyTag:(NSString *)keyTag withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(deletePrivateKey:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + + +RCT_EXTERN_METHOD(encrypt:(NSString *)message keyTag:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(decrypt:(NSString *)message keyTag:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(encrypt64:(NSString *)message keyTag:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(decrypt64:(NSString *)message keyTag:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +@end + + + + + + + diff --git a/ios/RNRSAKeychain.swift b/ios/RNRSAKeychain.swift new file mode 100644 index 00000000..b3c80659 --- /dev/null +++ b/ios/RNRSAKeychain.swift @@ -0,0 +1,225 @@ +// +// RNRSASwift.swift +// test +// +// Created by saeed kargosha. +// Copyright © 1398 saeed kargosha. All rights reserved. +// + +//#if canImport(React) +//import React +//#endif +import Foundation + +@objc(RNRSAKeychain) +class RNRSAKeychain: NSObject { + + + @objc + func constantsToExport() -> [AnyHashable : Any]! { + return[ + "SHA256withRSA": "SHA256withRSA", + "SHA512withRSA": "SHA512withRSA", + "SHA1withRSA" : "SHA1withRSA", + "SHA256withECDSA" : "SHA256withECDSA", + "SHA512withECDSA" : "SHA512withECDSA", + "SHA1withECDSA" : "SHA1withECDSA" + ] + } + + + + // generate key with default keysize - RSA - DER format + @objc + func generate(_ keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + // with default alogo RSA + let res = rsa_ec.generate(keySize: 2048) + if(res ?? false){ + let pub = rsa_ec.encodedPublicKeyDER() + let keys = ["public": pub] + resolve(keys) + return + } + resolve(false) + + } + + // generate key with keysize - RSA - DER format + @objc + func generateKeys(_ keyTag: String, keySize: Int, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + // with default alogo RSA + let res = rsa_ec.generate(keySize: keySize) + if(res ?? false){ + let pub = rsa_ec.encodedPublicKeyDER() + let keys = ["public": pub] + resolve(keys) + return + } + resolve(false) + } + + @objc + func generateCSR(_ keyTag: String, CN: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + + let rsa_ec = RSAECNative(keyTag: keyTag) + let csr = rsa_ec.generateCSR(CN: CN, withAlgorithm: withAlgorithm) + if(csr != nil){ + let keys = ["csr": csr] + resolve(keys) + }else { + reject("not exist CSR", "error", nil) + } + } + + @objc + func generateCSRWithEC(_ CN: String, keyTag: String, keySize: Int, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + + let rsa_ec = RSAECNative(keyTag: keyTag) + let res = rsa_ec.generateEC() + let pub = rsa_ec.encodedPublicKey() + let csr = rsa_ec.generateCSR(CN: CN, withAlgorithm: "SHA256withECDSA") + if(csr != nil){ + let keys = ["csr": csr, "public": pub] + resolve(keys) + }else { + reject("not exist CSR", "error", nil) + } + } + + @objc + func generateEC(_ keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + + let rsa_ec = RSAECNative(keyTag: keyTag) + let res = rsa_ec.generateEC() + if(res ?? false){ + let pub = rsa_ec.encodedPublicKey() + let keys = ["public": pub] + resolve(keys) + return + } + resolve(false) + } + + @objc + func signWithAlgorithm(_ message: String, keyTag: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let signature = rsa_ec.sign(message: message, withAlgorithm: withAlgorithm, withEncodeOption: NSData.Base64EncodingOptions(rawValue: 0)) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(signature) + } + } + + @objc + func sign64WithAlgorithm(_ message: String, keyTag: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let signature = rsa_ec.sign64(b64message: message, withAlgorithm: withAlgorithm) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(signature) + } + } + + // generate key with default keysize - DER format + @objc + func getPublicKeyDER(_ keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let pub = rsa_ec.encodedPublicKeyDER() + if(pub == nil){ + reject("not exist public key", "error", nil) + }else { + let keys = ["public": pub] + resolve(keys) + } + } + + // generate key with default keysize - DER format + @objc + func getPublicKey(_ keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let pub = rsa_ec.encodedPublicKey() + if(pub == nil){ + reject("not exist public key", "error", nil) + }else { + let keys = ["public": pub] + resolve(keys) + } + } + + // generate key with default keysize - DER format + @objc + func getPublicKeyRSA(_ keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let pub = rsa_ec.encodedPublicKeyRSA() + if(pub == nil){ + reject("not exist public key", "error", nil) + }else { + let keys = ["public": pub] + resolve(keys) + } + } + + @objc + func verifyWithAlgorithm(_ signature: String, withMessage: String ,keyTag: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let signature = rsa_ec.verify(encodedSignature: signature, withMessage: withMessage, withAlgorithm: withAlgorithm) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(true) + } + } + + @objc + func verify64WithAlgorithm(_ signature: String, withMessage: String ,keyTag: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let signature = rsa_ec.verify64(encodedSignature: signature, withMessage: withMessage, withAlgorithm: withAlgorithm) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(true) + } + } + + @objc + func deletePrivateKey(_ keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + rsa_ec.deletePrivateKey() + resolve(true) + } + + + @objc + func decrypt(_ message: String ,keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let msg = rsa_ec.decrypt(message: message) + resolve(msg) + } + + @objc + func encrypt(_ message: String ,keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let msg = rsa_ec.encrypt(message: message) + resolve(msg) + } + + @objc + func decrypt64(_ message: String ,keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let msg = rsa_ec.decrypt64(message: message) + resolve(msg) + } + + @objc + func encrypt64(_ message: String ,keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let msg = rsa_ec.encrypt64(message: message) + resolve(msg) + } + +} + diff --git a/ios/RSAECFormatter.swift b/ios/RSAECFormatter.swift new file mode 100644 index 00000000..5b2d1dea --- /dev/null +++ b/ios/RSAECFormatter.swift @@ -0,0 +1,76 @@ +// +// RSAECFormatter.swift +// BVLinearGradient +// +// Created by saeed kargosha. +// + +import Foundation + +class RSAECFormatter: NSObject { + + static let publicTag = "PUBLIC" + static let privateTag = "PRIVATE" + static let publicRsaTag = "RSA PUBLIC" + static let privateRsaTag = "RSA PRIVATE" + + static public func PEMFormattedPublicKeyRSA(publicKeyData: Data) -> String { + var encodedKey = Data() + encodedKey.append(publicKeyData) + return self.pemFormat(encodedKey: encodedKey, tag: publicRsaTag) + } + + static public func PEMFormattedPrivateKeyRSA(privateKeyData: Data) -> String { + var encodedKey = Data() + encodedKey.append(privateKeyData) + return self.pemFormat(encodedKey: encodedKey, tag: privateRsaTag) + } + + static public func PEMFormattedPublicKey(publicKeyData: Data) -> String { + var encodedKey = Data() + encodedKey.append(publicKeyData) + return self.pemFormat(encodedKey: encodedKey, tag: publicTag) + } + + static public func PEMFormattedPrivateKey(privateKeyData: Data) -> String { + var encodedKey = Data() + encodedKey.append(privateKeyData) + return self.pemFormat(encodedKey: encodedKey, tag: privateTag) + } + + static public func pemFormat(encodedKey: Data, tag: String) -> String { + + return String(format: "%@\n%@\n%@", + self.headerForTag(tag: tag), + encodedKey.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)), + self.footerForTag(tag: tag)) + } + + + static public func headerForTag(tag: String) -> String{ + return String(format: "-----BEGIN %@ KEY-----", tag) + } + + static public func footerForTag(tag: String) -> String { + return String(format: "-----END %@ KEY-----", tag) + } + + static public func stripHeaders(pemString: String) -> String? { + var str: String? = nil + if(pemString.contains(RSAECFormatter.headerForTag(tag: RSAECFormatter.privateRsaTag))){ + str = pemString.replacingOccurrences(of: RSAECFormatter.headerForTag(tag: RSAECFormatter.privateRsaTag), with: "") + str = str!.replacingOccurrences(of: RSAECFormatter.footerForTag(tag: RSAECFormatter.privateRsaTag), with: "") + }else if(pemString.contains(RSAECFormatter.headerForTag(tag: RSAECFormatter.privateTag))){ + str = pemString.replacingOccurrences(of: RSAECFormatter.headerForTag(tag: RSAECFormatter.privateTag), with: "") + str = str!.replacingOccurrences(of: RSAECFormatter.footerForTag(tag: RSAECFormatter.privateTag), with: "") + }else if(pemString.contains(RSAECFormatter.headerForTag(tag: RSAECFormatter.publicRsaTag))){ + str = pemString.replacingOccurrences(of: RSAECFormatter.headerForTag(tag: RSAECFormatter.publicRsaTag), with: "") + str = str!.replacingOccurrences(of: RSAECFormatter.footerForTag(tag: RSAECFormatter.publicRsaTag), with: "") + }else if(pemString.contains(RSAECFormatter.headerForTag(tag: RSAECFormatter.publicTag))){ + str = pemString.replacingOccurrences(of: RSAECFormatter.headerForTag(tag: RSAECFormatter.publicTag), with: "") + str = str!.replacingOccurrences(of: RSAECFormatter.footerForTag(tag: RSAECFormatter.publicTag), with: "") + } + return str + } + +} diff --git a/ios/RSAECNative.swift b/ios/RSAECNative.swift new file mode 100644 index 00000000..b9bb1bb6 --- /dev/null +++ b/ios/RSAECNative.swift @@ -0,0 +1,612 @@ + + +// +// RSANative.swift +// BVLinearGradient +// +// Created by saeed kargosha. +// + +import Foundation +import CommonCrypto + +typealias SecKeyPerformBlock = (SecKey) -> () + + +class RSAECNative: NSObject { + + var publicKey: SecKey? + var privateKey: SecKey? + var keyTag: String? + let publicKeyTag: String? + let privateKeyTag: String? + var publicKeyBits: Data? + var keyAlgorithm = KeyAlgorithm.rsa(signatureType: .sha1) + + public init(keyTag: String?){ + self.publicKeyTag = "\(keyTag ?? "").public" + self.privateKeyTag = "\(keyTag ?? "").private" + self.keyTag = keyTag + super.init() + } + + public convenience override init(){ + self.init(keyTag: nil) + } + + public func generate(keySize: Int) -> Bool? { + var publicKeyParameters: [String: AnyObject] = [ + String(kSecAttrAccessible): kSecAttrAccessibleAlways, + ] + + var privateKeyParameters: [String: AnyObject] = [ + String(kSecAttrAccessible): kSecAttrAccessibleAlways, + ] + + if((self.keyTag) != nil){ + privateKeyParameters[String(kSecAttrIsPermanent)] = kCFBooleanTrue + privateKeyParameters[String(kSecAttrApplicationTag)] = self.privateKeyTag as AnyObject + + publicKeyParameters[String(kSecAttrIsPermanent)] = kCFBooleanTrue + publicKeyParameters[String(kSecAttrApplicationTag)] = self.publicKeyTag as AnyObject + + } + + #if !arch(i386) && !arch(x86_64) + //This only works for Secure Enclave consistign of 256 bit key, note, the signatureType is irrelavent for this check + if keyAlgorithm.type == KeyAlgorithm.ec(signatureType: .sha1).type{ + let access = SecAccessControlCreateWithFlags(kCFAllocatorDefault, + kSecAttrAccessibleAlwaysThisDeviceOnly, + .privateKeyUsage, + nil)! // Ignore error + + privateKeyParameters[String(kSecAttrAccessControl)] = access + } + #endif + + //Define what type of keys to be generated here + var parameters: [String: AnyObject] = [ + String(kSecReturnRef): kCFBooleanTrue, + kSecPublicKeyAttrs as String: publicKeyParameters as AnyObject, + kSecPrivateKeyAttrs as String: privateKeyParameters as AnyObject, + ] + parameters[String(kSecAttrKeySizeInBits)] = keySize as AnyObject + if #available(iOS 10, *) { + parameters[String(kSecAttrKeyType)] = keyAlgorithm.secKeyAttrType + } else { + // Fallback on earlier versions + parameters[String(kSecAttrKeyType)] = keyAlgorithm.secKeyAttrTypeiOS9 + } + + #if !arch(i386) && !arch(x86_64) + + //iOS only allows EC 256 keys to be secured in enclave. This will attempt to allow any EC key in the enclave, assuming iOS will do it outside of the enclave if it doesn't like the key size, note: the signatureType is irrelavent for this check + if keyAlgorithm.type == KeyAlgorithm.ec(signatureType: .sha1).type{ + parameters[String(kSecAttrTokenID)] = kSecAttrTokenIDSecureEnclave + } + + #endif + + // TODO: Fix for when not set keytag and dont use keychain + if #available(iOS 10.0, *) { + + var error: Unmanaged? + self.privateKey = SecKeyCreateRandomKey(parameters as CFDictionary, &error) + + if self.privateKey == nil { + print("Error occured: keys weren't created") + return nil + } + + self.publicKey = SecKeyCopyPublicKey(self.privateKey!) + + } else { + // Fallback on earlier versions + + let result = SecKeyGeneratePair(parameters as CFDictionary, &publicKey, &privateKey) + + if result != errSecSuccess{ + print("Error occured: \(result)") + return nil + } + } + + guard self.publicKey != nil else { + print( "Error in setUp(). PublicKey shouldn't be nil") + return nil + } + + guard self.privateKey != nil else{ + print("Error in setUp(). PrivateKey shouldn't be nil") + return nil + } + return true + } + + public func generateEC() -> Bool? { + self.keyAlgorithm = KeyAlgorithm.ec(signatureType: .sha256) + // ios support 256 + return self.generate(keySize: 256); + } + + public func generateCSR(CN: String?, withAlgorithm: String) -> String? { + self.setAlgorithm(algorithm: withAlgorithm) + // self.privateKey = self.getPrivateKeyChain(tag: self.privateKeyTag!) + self.publicKeyBits = self.getPublicKeyChainData(tag: self.publicKeyTag!) + var csrString: String? + let csrBlock: SecKeyPerformBlock = { privateKey in + let csr = CertificateSigningRequest(commonName: CN, organizationName: nil, organizationUnitName: nil, countryName: nil, stateOrProvinceName: nil, localityName: nil, keyAlgorithm: self.keyAlgorithm) + csrString = csr.buildCSRAndReturnString(self.publicKeyBits!, privateKey: privateKey) + } + + if ((self.keyTag) != nil) { + self.performWithPrivateKeyTag(keyTag: self.privateKeyTag!, block: csrBlock) + } else { + csrBlock(self.privateKey!); + } + return csrString + } + + private func getPublicKeyChainData(tag : String) -> Data? { + //Ask keychain to provide the publicKey in bits + var query: [String: AnyObject] = [ + String(kSecClass): kSecClassKey, + String(kSecAttrApplicationTag): self.publicKeyTag as AnyObject, + String(kSecReturnData): kCFBooleanTrue + ] + + if #available(iOS 10, *) { + query[String(kSecAttrKeyType)] = self.keyAlgorithm.secKeyAttrType + } else { + // Fallback on earlier versions + query[String(kSecAttrKeyType)] = self.keyAlgorithm.secKeyAttrTypeiOS9 + } + + var tempPublicKeyBits:AnyObject? + + let result = SecItemCopyMatching(query as CFDictionary, &tempPublicKeyBits) + + switch result { + case errSecSuccess: + guard let keyBits = tempPublicKeyBits as? Data else { + print("error in: convert to publicKeyBits") + return nil + } + return keyBits + + default: + print("error in: convert to publicKeyBits") + return nil + } + } + + private func setAlgorithm(algorithm: String) -> Void { + switch algorithm { + case "SHA256withRSA": + self.keyAlgorithm = .rsa(signatureType: .sha256) + case "SHA512withRSA": + self.keyAlgorithm = .rsa(signatureType: .sha512) + case "SHA1withRSA": + self.keyAlgorithm = .rsa(signatureType: .sha1) + case "SHA256withECDSA": + self.keyAlgorithm = .ec(signatureType: .sha256) + case "SHA512withECDSA": + self.keyAlgorithm = .ec(signatureType: .sha512) + case "SHA1withECDSA": + self.keyAlgorithm = .ec(signatureType: .sha1) + default: + self.keyAlgorithm = .rsa(signatureType: .sha1) + } + } + + + public func deletePrivateKey(){ + var query: [String: AnyObject] = [ + String(kSecClass) : kSecClassKey, + String(kSecAttrApplicationTag): self.privateKeyTag as AnyObject, + String(kSecReturnRef) : true as AnyObject + ] + + if #available(iOS 10, *) { + query[String(kSecAttrKeyType)] = self.keyAlgorithm.secKeyAttrType + } else { + // Fallback on earlier versions + query[String(kSecAttrKeyType)] = self.keyAlgorithm.secKeyAttrTypeiOS9 + } + let result = SecItemDelete(query as CFDictionary) + + if result != errSecSuccess{ + print("Error delete private key: \(result)") + // return nil + } + } + + public func encodedPublicKeyRSA() -> String? { + if ((self.keyTag) != nil) { + var encodedPublicKey: String? + self.performWithPublicKeyTag(tag: self.publicKeyTag!) { (publicKey) in + encodedPublicKey = self.externalRepresentationForPublicKeyRSA(key: publicKey) + } + return encodedPublicKey; + } + if(self.publicKey == nil) { return nil } + return self.externalRepresentationForPublicKeyRSA(key: self.publicKey!) + } + + public func encodedPublicKeyDER() -> String? { + + if ((self.keyTag) != nil) { + var encodedPublicKey: String? + self.performWithPublicKeyTag(tag: self.publicKeyTag!) { (publicKey) in + encodedPublicKey = self.externalRepresentationForPublicKeyDER(key: publicKey) + } + return encodedPublicKey; + } + if(self.publicKey == nil) { return nil } + return self.externalRepresentationForPublicKeyDER(key: self.publicKey!) + } + + public func encodedPublicKey() -> String? { + + if ((self.keyTag) != nil) { + var encodedPublicKey: String? + self.performWithPublicKeyTag(tag: self.publicKeyTag!) { (publicKey) in + encodedPublicKey = self.externalRepresentationForPublicKey(key: publicKey) + } + return encodedPublicKey; + } + if(self.publicKey == nil) { return nil } + return self.externalRepresentationForPublicKey(key: self.publicKey!) + } + + public func encodedPrivateKeyRSA() -> String? { + if ((self.keyTag) != nil) { + var encodedPrivateKey: String? + self.performWithPrivateKeyTag(keyTag: self.privateKeyTag!) { (privateKey) in + encodedPrivateKey = self.externalRepresentationForPrivateKeyRSA(key: privateKey) + } + return encodedPrivateKey; + } + if(self.privateKey == nil) { return nil } + return self.externalRepresentationForPrivateKeyRSA(key: self.privateKey!) + } + + public func encodedPrivateKeyDER() -> String? { + if ((self.keyTag) != nil) { + var encodedPrivateKey: String? + self.performWithPrivateKeyTag(keyTag: self.privateKeyTag!) { (privateKey) in + encodedPrivateKey = self.externalRepresentationForPrivateKeyDER(key: privateKey) + } + return encodedPrivateKey; + } + if(self.privateKey == nil) { return nil } + return self.externalRepresentationForPrivateKeyDER(key: self.privateKey!) + } + + + public func setPublicKey(publicKey: String) -> Bool? { + guard let publicKeyStr = RSAECFormatter.stripHeaders(pemString: publicKey) else { return false } + let query: [String: AnyObject] = [ + String(kSecAttrKeyType): kSecAttrKeyTypeRSA, + String(kSecAttrKeyClass): kSecAttrKeyClassPublic, + ] + print(publicKeyStr, "publicKeyStrpublicKeyStr") + var error: Unmanaged? + guard let data = Data(base64Encoded: publicKeyStr, options: .ignoreUnknownCharacters) else { return false } + print(data, "datadatadata") + if #available(iOS 10.0, *) { + guard let key = SecKeyCreateWithData(data as CFData, query as CFDictionary, &error) else { return false } + self.publicKey = key + return true + } else { + // Fallback on earlier versions + } + return false + } + + public func setPrivateKey(privateKey: String) -> Bool? { + guard let privateKeyStr = RSAECFormatter.stripHeaders(pemString: privateKey) else { return nil } + let query: [String: AnyObject] = [ + String(kSecAttrKeyType): kSecAttrKeyTypeRSA, + String(kSecAttrKeyClass): kSecAttrKeyClassPrivate, + ] + var error: Unmanaged? + guard let data = Data(base64Encoded: privateKeyStr, options: .ignoreUnknownCharacters) else { return nil } + if #available(iOS 10.0, *) { + guard let key = SecKeyCreateWithData(data as CFData, query as CFDictionary, &error) else { return nil } + self.privateKey = key + return true + } else { + // Fallback on earlier versions + } + return nil + } + + public func encrypt64(message: String) -> String? { + guard let data = Data(base64Encoded: message, options: .ignoreUnknownCharacters) else { return nil } + let encrypted = self._encrypt(data: data) + return encrypted?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) + } + + + public func encrypt(message: String) -> String? { + guard let data = message.data(using: .utf8) else { return nil } + let encrypted = self._encrypt(data: data) + return encrypted?.base64EncodedString(options: .lineLength64Characters) + } + + public func _encrypt(data: Data) -> Data? { + var cipherText: Data? + + // Closures + let encryptor:SecKeyPerformBlock = { publicKey in + if #available(iOS 10.0, *) { + let canEncrypt = SecKeyIsAlgorithmSupported(publicKey, .encrypt, .rsaEncryptionPKCS1) + if(canEncrypt){ + var error: Unmanaged? + cipherText = SecKeyCreateEncryptedData(publicKey, .rsaEncryptionPKCS1, data as CFData, &error) as Data? + } + } else { + // Fallback on earlier versions + }; + } + + + if ((self.keyTag) != nil) { + self.performWithPublicKeyTag(tag: self.publicKeyTag!, block: encryptor) + } else { + encryptor(self.publicKey!); + } + return cipherText; + } + + public func decrypt64(message: String) -> String? { + guard let data = Data(base64Encoded: message, options: .ignoreUnknownCharacters) else { return nil } + let decrypted = self._decrypt(data: data) + return decrypted?.base64EncodedString(options: NSData.Base64EncodingOptions(rawValue: 0)) + } + + + public func decrypt(message: String) -> String? { + guard let data = Data(base64Encoded: message, options: .ignoreUnknownCharacters) else { return nil } + let decrypted = self._decrypt(data: data) + return String(data: decrypted!, encoding: String.Encoding.utf8) + } + + private func _decrypt(data: Data) -> Data? { + var clearText: Data? + let decryptor: SecKeyPerformBlock = {privateKey in + if #available(iOS 10.0, *) { + let canEncrypt = SecKeyIsAlgorithmSupported(privateKey, .decrypt, .rsaEncryptionPKCS1) + if(canEncrypt){ + var error: Unmanaged? + clearText = SecKeyCreateDecryptedData(privateKey, .rsaEncryptionPKCS1, data as CFData, &error) as Data? + } + + } else { + // Fallback on earlier versions + }; + } + + if ((self.keyTag) != nil) { + self.performWithPrivateKeyTag(keyTag: self.privateKeyTag!, block: decryptor) + } else { + decryptor(self.privateKey!); + } + return clearText + } + + public func sign64(b64message: String, withAlgorithm: String) -> String? { + guard let data = Data(base64Encoded: b64message, options: .ignoreUnknownCharacters) else { return nil } + let encodedSignature = self._sign(messageBytes: data, withAlgorithm: withAlgorithm, withEncodeOption: .lineLength64Characters) + return encodedSignature + } + + public func sign(message: String, withAlgorithm: String, withEncodeOption: NSData.Base64EncodingOptions) -> String? { + guard let data = message.data(using: .utf8) else { return nil } + let encodedSignature = self._sign(messageBytes: data, withAlgorithm: withAlgorithm, withEncodeOption: withEncodeOption) + return encodedSignature + } + + private func _sign(messageBytes: Data, withAlgorithm: String, withEncodeOption: NSData.Base64EncodingOptions) -> String? { + self.setAlgorithm(algorithm: withAlgorithm) + var encodedSignature: String? + let signer: SecKeyPerformBlock = { privateKey in + if #available(iOS 11, *) { + // Build signature - step 1: SHA1 hash + // Build signature - step 2: Sign hash + // var signature: Data? = nil + var error: Unmanaged? + + let signature = SecKeyCreateSignature(privateKey, self.keyAlgorithm.signatureAlgorithm, messageBytes as CFData, &error) as Data? + + if error != nil{ + print("Error in creating signature: \(error!.takeRetainedValue())") + } + + encodedSignature = signature!.base64EncodedString(options: withEncodeOption) + + } else { + // TODO: fix and test + // Fallback on earlier versions + + // Build signature - step 1: SHA1 hash + var signature = [UInt8](repeating: 0, count: self.keyAlgorithm.availableKeySizes.last!) + var signatureLen:Int = signature.count + var messageDataBytes = [UInt8](repeating: 0, count: messageBytes.count) + messageBytes.copyBytes(to: &messageDataBytes, count: messageBytes.count) + var digest = [UInt8](repeating: 0, count: self.keyAlgorithm.digestLength) + let padding = self.keyAlgorithm.padding + + switch self.keyAlgorithm { + + case .rsa(signatureType: .sha1), .ec(signatureType: .sha1): + + var SHA1 = CC_SHA1_CTX() + CC_SHA1_Init(&SHA1) + CC_SHA1_Update(&SHA1, messageDataBytes, CC_LONG(messageBytes.count)) + + CC_SHA1_Final(&digest, &SHA1) + + case .rsa(signatureType: .sha256), .ec(signatureType: .sha256): + + var SHA256 = CC_SHA256_CTX() + CC_SHA256_Init(&SHA256) + CC_SHA256_Update(&SHA256, messageDataBytes, CC_LONG(messageBytes.count)) + CC_SHA256_Final(&digest, &SHA256) + + case .rsa(signatureType: .sha512), .ec(signatureType: .sha512): + + var SHA512 = CC_SHA512_CTX() + CC_SHA512_Init(&SHA512) + CC_SHA512_Update(&SHA512, messageDataBytes, CC_LONG(messageBytes.count)) + CC_SHA512_Final(&digest, &SHA512) + + } + + // Build signature - step 2: Sign hash + let result = SecKeyRawSign(privateKey, padding, digest, digest.count, &signature, &signatureLen) + + if result != errSecSuccess{ + print("Error signing: \(result)") + return + } + var signData = Data() + let zero:UInt8 = 0 + signData.append(zero) + signData.append(signature, count: signatureLen) + encodedSignature = signData.base64EncodedString(options: withEncodeOption) + } + } + + if ((self.keyTag) != nil) { + self.performWithPrivateKeyTag(keyTag: self.privateKeyTag!, block: signer) + } else { + signer(self.privateKey!); + } + + return encodedSignature + } + + public func verify64(encodedSignature: String, withMessage: String, withAlgorithm: String) -> Bool? { + guard let messageBytes = Data(base64Encoded: encodedSignature, options: .ignoreUnknownCharacters) else { return nil } + guard let signatureBytes = Data(base64Encoded: withMessage, options: .ignoreUnknownCharacters) else { return nil } + return self._verify(signatureBytes: messageBytes, withMessage: signatureBytes, withAlgorithm: withAlgorithm) + } + + public func verify(encodedSignature: String, withMessage: String, withAlgorithm: String) -> Bool? { + guard let messageBytes = encodedSignature.data(using: .utf8) else { return nil } + guard let signatureBytes = Data(base64Encoded: withMessage, options: .ignoreUnknownCharacters) else { return nil } + return self._verify(signatureBytes: messageBytes, withMessage: signatureBytes, withAlgorithm: withAlgorithm) + } + + private func _verify(signatureBytes: Data, withMessage: Data, withAlgorithm: String) -> Bool? { + var result = false + + // Closures + let verifier: SecKeyPerformBlock = { publicKey in + if #available(iOS 10.0, *) { + var error: Unmanaged? + result = SecKeyVerifySignature(publicKey, self.keyAlgorithm.signatureAlgorithm, withMessage as CFData, signatureBytes as CFData, &error) + } else { + // Fallback on earlier versions + } + } + + + if ((self.keyTag) != nil) { + self.performWithPublicKeyTag(tag: self.publicKeyTag!, block: verifier) + } else { + verifier(self.publicKey!); + } + return result + } + + private func performWithPrivateKeyTag(keyTag: String, block: SecKeyPerformBlock){ + var query: [String: AnyObject] = [ + String(kSecClass) : kSecClassKey, + String(kSecAttrApplicationTag): keyTag as AnyObject, + String(kSecReturnRef) : true as AnyObject + ] + + if #available(iOS 10, *) { + query[String(kSecAttrKeyType)] = self.keyAlgorithm.secKeyAttrType + } else { + // Fallback on earlier versions + query[String(kSecAttrKeyType)] = self.keyAlgorithm.secKeyAttrTypeiOS9 + } + + var result : AnyObject? + + let status = SecItemCopyMatching(query as CFDictionary, &result) + + if status == errSecSuccess { + print("\(keyTag) Key existed!") + block((result as! SecKey?)!) + } + } + + private func performWithPublicKeyTag(tag: String, block: SecKeyPerformBlock){ + self.performWithPrivateKeyTag(keyTag: self.privateKeyTag!) { (privateKey) in + if #available(iOS 10.0, *) { + let publicKey = SecKeyCopyPublicKey(privateKey) + block(publicKey!) + } else { + // Fallback on earlier versions + } + } + + } + + + private func externalRepresentationForPublicKeyRSA(key: SecKey) -> String? { + guard let data = self.dataForKey(key: key) else { return nil } + return RSAECFormatter.PEMFormattedPublicKeyRSA(publicKeyData: data) + } + + private func externalRepresentationForPublicKey(key: SecKey) -> String? { + guard let data = self.dataForKey(key: key) else { return nil } + return RSAECFormatter.PEMFormattedPublicKey(publicKeyData: data) + } + + private func externalRepresentationForPublicKeyDER(key: SecKey) -> String? { + guard let data = self.dataForKey(key: key) else { return nil } + let convertedData = RSAKeyEncoding().convertToX509EncodedKey(data) + return RSAECFormatter.PEMFormattedPublicKey(publicKeyData: convertedData) + } + + private func externalRepresentationForPrivateKeyRSA(key: SecKey) -> String? { + guard let data = self.dataForKey(key: key) else { return nil } + return RSAECFormatter.PEMFormattedPrivateKeyRSA(privateKeyData: data) + } + + private func externalRepresentationForPrivateKeyDER(key: SecKey) -> String? { + guard let data = self.dataForKey(key: key) else { return nil } + let convertedData = RSAKeyEncoding().convertToX509EncodedKey(data) + return RSAECFormatter.PEMFormattedPrivateKey(privateKeyData: convertedData) + } + + private func externalRepresentationForPrivateKey(key: SecKey) -> String? { + guard let data = self.dataForKey(key: key) else { return nil } + return RSAECFormatter.PEMFormattedPrivateKey(privateKeyData: data) + } + + private func dataForKey(key: SecKey) -> Data? { + var error: Unmanaged? + var keyData: Data? + if #available(iOS 10.0, *) { + keyData = SecKeyCopyExternalRepresentation(key, &error) as Data? + } else { + // Fallback on earlier versions + } + + if (keyData == nil) { + print("error in dataForKey") + return nil + } + + return keyData; + } + +} + diff --git a/ios/RSAFormatter.h b/ios/RSAFormatter.h deleted file mode 100644 index 1d0cd8fc..00000000 --- a/ios/RSAFormatter.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// RSAFormatter.h -// RNRSA -// -// Created by Amitay Molko on 30/06/2017. -// Copyright © 2017 RNRSA. All rights reserved. -// - -@import Foundation; - -@interface RSAFormatter : NSObject - -+ (NSString *)PEMFormattedPublicKey:(NSData *)publicKeyData; -+ (NSString *)PEMFormattedPrivateKey:(NSData *)privateKeyData; -+ (NSString *)stripHeaders:(NSString *)pemString; - -@end diff --git a/ios/RSAFormatter.m b/ios/RSAFormatter.m deleted file mode 100644 index 9e5195be..00000000 --- a/ios/RSAFormatter.m +++ /dev/null @@ -1,72 +0,0 @@ -// -// RNRSAFormatter.m -// RNRSA -// -// Created by Amitay Molko on 30/06/2017. -// Copyright © 2017 RNRSA. All rights reserved. -// - -#import "RSAFormatter.h" - -@implementation RSAFormatter - -static NSString *publicTag = @"PUBLIC"; -static NSString *privateTag = @"PRIVATE"; -static NSString *publicRsaTag = @"RSA PUBLIC"; -static NSString *privateRsaTag = @"RSA PRIVATE"; - -+ (NSString *)PEMFormattedPublicKey:(NSData *)publicKeyData { - NSMutableData * encodedKey = [[NSMutableData alloc] init]; - [encodedKey appendData:publicKeyData]; - return [self pemFormat:encodedKey tag:publicRsaTag]; -} - -+ (NSString *)PEMFormattedPrivateKey:(NSData *)privateKeyData { - NSMutableData * encodedKey = [[NSMutableData alloc] init]; - [encodedKey appendData:privateKeyData]; - return [self pemFormat:encodedKey tag:privateRsaTag]; -} - -+ (NSString *)pemFormat:(NSData *)encodedKey tag:(NSString *)tag { - return [NSString stringWithFormat:@"%@\n%@\n%@", - [self headerForTag:tag], - [encodedKey base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength], - [self footerForTag:tag] - ]; -} - -+ (NSString *)headerForTag:(NSString *)tag { - return [NSString stringWithFormat:@"-----BEGIN %@ KEY-----", tag ]; -} - -+ (NSString *)footerForTag:(NSString *)tag { - return [NSString stringWithFormat:@"-----END %@ KEY-----", tag]; -} - -+ (NSString *)stripHeaders:(NSString *)pemString { - NSRange spos; - NSRange epos; - if ([pemString rangeOfString:[self headerForTag:privateRsaTag]].length > 0) { - spos = [pemString rangeOfString:[self headerForTag:privateRsaTag]]; - epos = [pemString rangeOfString:[self footerForTag:privateRsaTag]]; - } else if ([pemString rangeOfString:[self headerForTag:publicRsaTag]].length > 0) { - spos = [pemString rangeOfString:[self headerForTag:publicRsaTag]]; - epos = [pemString rangeOfString:[self footerForTag:publicRsaTag]]; - } else if ([pemString rangeOfString:[self headerForTag:privateTag]].length > 0) { - spos = [pemString rangeOfString:[self headerForTag:privateTag]]; - epos = [pemString rangeOfString:[self footerForTag:privateTag]]; - } else if ([pemString rangeOfString:[self headerForTag:publicTag]].length > 0) { - spos = [pemString rangeOfString:[self headerForTag:publicTag]]; - epos = [pemString rangeOfString:[self footerForTag:publicTag]]; - } - - if(spos.location != NSNotFound && epos.location != NSNotFound){ - NSUInteger s = spos.location + spos.length; - NSUInteger e = epos.location; - NSRange range = NSMakeRange(s, e-s); - pemString = [pemString substringWithRange:range]; - } - return pemString; -} - -@end diff --git a/ios/RSAKeyEncoding.swift b/ios/RSAKeyEncoding.swift new file mode 100644 index 00000000..5b312165 --- /dev/null +++ b/ios/RSAKeyEncoding.swift @@ -0,0 +1,85 @@ +// +// RSAKeyEncoding.swift +// RNECRSA +// +// Created by saeed kargosha. +// Copyright © 1398 saeed kargosha. All rights reserved. +// + +import Foundation + +class RSAKeyEncoding: NSObject { + + // ASN.1 identifiers + private let bitStringIdentifier: UInt8 = 0x03 + private let sequenceIdentifier: UInt8 = 0x30 + + // ASN.1 AlgorithmIdentfier for RSA encryption: OID 1 2 840 113549 1 1 1 and NULL + private let algorithmIdentifierForRSAEncryption: [UInt8] = [0x30, 0x0d, 0x06, + 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00] + + /// Converts the DER encoding of an RSA public key that is either fetched from the + /// keychain (e.g. by using `SecItemCopyMatching(_:_:)`) or retrieved in another way + /// (e.g. by using `SecKeyCopyExternalRepresentation(_:_:)`), to a format typically + /// used by tools and programming languages outside the Apple ecosystem (such as + /// OpenSSL, Java, PHP and Perl). The DER encoding of an RSA public key created by + /// iOS is represented with the ASN.1 RSAPublicKey type as defined by PKCS #1. + /// However, many systems outside the Apple ecosystem expect the DER encoding of a + /// key to be represented with the ASN.1 SubjectPublicKeyInfo type as defined by + /// X.509. The two types are related in a way that if the SubjectPublicKeyInfo’s + /// algorithm field contains the rsaEncryption object identifier as defined by + /// PKCS #1, the subjectPublicKey field shall contain the DER encoding of an + /// RSAPublicKey type. + /// + /// - Parameter rsaPublicKeyData: A data object containing the DER encoding of an + /// RSA public key, which is represented with the ASN.1 RSAPublicKey type. + /// - Returns: A data object containing the DER encoding of an RSA public key, which + /// is represented with the ASN.1 SubjectPublicKeyInfo type. + func convertToX509EncodedKey(_ rsaPublicKeyData: Data) -> Data { + var derEncodedKeyBytes = [UInt8](rsaPublicKeyData) + + // Insert ASN.1 BIT STRING bytes at the beginning of the array + derEncodedKeyBytes.insert(0x00, at: 0) + derEncodedKeyBytes.insert(contentsOf: lengthField(of: derEncodedKeyBytes), at: 0) + derEncodedKeyBytes.insert(bitStringIdentifier, at: 0) + + // Insert ASN.1 AlgorithmIdentifier bytes at the beginning of the array + derEncodedKeyBytes.insert(contentsOf: algorithmIdentifierForRSAEncryption, at: 0) + + // Insert ASN.1 SEQUENCE bytes at the beginning of the array + derEncodedKeyBytes.insert(contentsOf: lengthField(of: derEncodedKeyBytes), at: 0) + derEncodedKeyBytes.insert(sequenceIdentifier, at: 0) + + return Data(derEncodedKeyBytes) + } + + private func lengthField(of valueField: [UInt8]) -> [UInt8] { + var length = valueField.count + + if length < 128 { + return [ UInt8(length) ] + } + + // Number of bytes needed to encode the length + let lengthBytesCount = Int((log2(Double(length)) / 8) + 1) + + // First byte encodes the number of remaining bytes in this field + let firstLengthFieldByte = UInt8(128 + lengthBytesCount) + + var lengthField: [UInt8] = [] + for _ in 0..> 8 + } + + // Insert firstLengthFieldByte at the beginning of the array + lengthField.insert(firstLengthFieldByte, at: 0) + + return lengthField + } +} + diff --git a/ios/RSANative.h b/ios/RSANative.h deleted file mode 100644 index bc2d55a1..00000000 --- a/ios/RSANative.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// RSA.h -// RNRSA -// -// Created by Amitay Molko on 24/06/2017. -// Copyright © 2017 Facebook. All rights reserved. -// - -@import Foundation; - -@interface RSANative : NSObject - -@property (nonatomic) NSString *publicKey; -@property (nonatomic) NSString *privateKey; - -- (instancetype)initWithKeyTag:(NSString *)keyTag; - -- (void)generate:(int)keySize; -- (void)deletePrivateKey; - -- (NSString *)encodedPublicKey; -- (NSString *)encodedPrivateKey; - -- (NSString *)encrypt:(NSString *)message; -- (NSString *)decrypt:(NSString *)encodedMessage; - -- (NSString *)encrypt64:(NSString *)message; -- (NSString *)decrypt64:(NSString *)encodedMessage; - -- (NSData *)_encrypt:(NSData *)message; -- (NSData *)_decrypt:(NSData *)encodedMessage; - -- (NSString *)sign:(NSString *)message withAlgorithm:(NSString *)algorithm withEncodeOption: (NSDataBase64EncodingOptions)encodeOption; -- (BOOL)verify:(NSString *)signature withMessage:(NSString *)message withAlgorithm:(NSString *)verifyAlgorithm; - -- (NSString *)sign64:(NSString *)b64message withAlgorithm:(NSString *)verifyAlgorithm; -- (BOOL)verify64:(NSString *)signature withMessage:(NSString *)b64message withAlgorithm:(NSString *)verifyAlgorithm; - -- (NSString *)_sign:(NSData *)messageBytes; -- (BOOL)_verify:(NSData *)signatureBytes withMessage:(NSData *)messageBytes; - -@end diff --git a/ios/RSANative.m b/ios/RSANative.m deleted file mode 100644 index ae055a4f..00000000 --- a/ios/RSANative.m +++ /dev/null @@ -1,371 +0,0 @@ -#import "RSANative.h" -#import "RSAFormatter.h" - -// Code largely based on practices as defined by: -// https://developer.apple.com/library/content/documentation/Security/Conceptual/CertKeyTrustProgGuide/KeyRead.html#//apple_ref/doc/uid/TP40001358-CH222-SW1 - -typedef void (^SecKeyPerformBlock)(SecKeyRef key); - -@interface RSANative () -@property (nonatomic) NSString *keyTag; -@property (nonatomic) SecKeyRef publicKeyRef; -@property (nonatomic) SecKeyRef privateKeyRef; -@end - -@implementation RSANative - -- (instancetype)initWithKeyTag:(NSString *)keyTag { - self = [super init]; - if (self) { - _keyTag = keyTag; - } - return self; -} - -- (void)generate:(int)keySize { - NSMutableDictionary *privateKeyAttributes = [NSMutableDictionary dictionary]; - - if (self.keyTag) { - NSData *tag = [self.keyTag dataUsingEncoding:NSUTF8StringEncoding]; - - privateKeyAttributes[(id)kSecAttrIsPermanent] = @YES; // store in keychain - privateKeyAttributes[(id)kSecAttrApplicationTag] = tag; - } - - NSMutableDictionary *attributes = [[NSMutableDictionary alloc] init]; - [attributes setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; - [attributes setObject:[NSNumber numberWithInt:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits]; - [attributes setObject:privateKeyAttributes forKey:(__bridge id)kSecPrivateKeyAttrs]; - - CFErrorRef error = NULL; - SecKeyRef privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)attributes, &error); - - if (!privateKey) { - NSError *err = CFBridgingRelease(error); - NSLog(@"%@", err); - } - - if (!self.keyTag) { // no keychain being used, store reference to keys for later use - _privateKeyRef = privateKey; - _publicKeyRef = SecKeyCopyPublicKey(privateKey); - } -} - -- (void)deletePrivateKey { - if (self.keyTag) { - NSDictionary *getquery = @{ (id)kSecClass: (id)kSecClassKey, - (id)kSecAttrApplicationTag: self.keyTag, - (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, - }; - SecItemDelete((CFDictionaryRef)getquery); - } else { - self.privateKey = nil; - } -} - -- (NSString *)encodedPublicKey { - if (self.keyTag) { - __block NSString *encodedPublicKey = nil; - - [self performWithPublicKeyTag:self.keyTag block:^(SecKeyRef publicKey) { - encodedPublicKey = [self externalRepresentationForPublicKey:publicKey]; - }]; - - return encodedPublicKey; - } - - return [self externalRepresentationForPublicKey:self.publicKeyRef]; -} - -- (NSString *)encodedPrivateKey { - if (self.keyTag) { - __block NSString *encodedPrivateKey = nil; - - [self performWithPrivateKeyTag:self.keyTag block:^(SecKeyRef privateKey) { - encodedPrivateKey = [self externalRepresentationForPrivateKey:privateKey]; - }]; - - return encodedPrivateKey; - } - - return [self externalRepresentationForPrivateKey:self.privateKeyRef]; -} - -- (void)setPublicKey:(NSString *)publicKey { - publicKey = [RSAFormatter stripHeaders: publicKey]; - NSDictionary* options = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, - (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic, -// (id)kSecAttrKeySizeInBits: @2048, - }; - CFErrorRef error = NULL; - NSData *data = [[NSData alloc] initWithBase64EncodedString:publicKey options:NSDataBase64DecodingIgnoreUnknownCharacters]; - SecKeyRef key = SecKeyCreateWithData((__bridge CFDataRef)data, - (__bridge CFDictionaryRef)options, - &error); - if (!key) { - NSError *err = CFBridgingRelease(error); - NSLog(@"%@", err); - } else { - _publicKeyRef = key; - } -} - -- (void)setPrivateKey:(NSString *)privateKey { - privateKey = [RSAFormatter stripHeaders: privateKey]; - - NSDictionary* options = @{(id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, - (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate, -// (id)kSecAttrKeySizeInBits: @2048, - }; - CFErrorRef error = NULL; - NSData *data = [[NSData alloc] initWithBase64EncodedString:privateKey options:NSDataBase64DecodingIgnoreUnknownCharacters]; - SecKeyRef key = SecKeyCreateWithData((__bridge CFDataRef)data, - (__bridge CFDictionaryRef)options, - &error); - if (!key) { - NSError *err = CFBridgingRelease(error); - NSLog(@"%@", err); - } else { - _privateKeyRef = key; - } -} - -- (NSString *)encrypt64:(NSString*)message { - NSData *data = [[NSData alloc] initWithBase64EncodedString:message options:NSDataBase64DecodingIgnoreUnknownCharacters]; - NSData *encrypted = [self _encrypt: data]; - return [encrypted base64EncodedStringWithOptions:0]; -} - -- (NSString *)encrypt:(NSString *)message { - NSData *data = [message dataUsingEncoding:NSUTF8StringEncoding]; - NSData *encrypted = [self _encrypt: data]; - return [encrypted base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; -} - -- (NSData *)_encrypt:(NSData *)data { - __block NSData *cipherText = nil; - - void(^encryptor)(SecKeyRef) = ^(SecKeyRef publicKey) { - BOOL canEncrypt = SecKeyIsAlgorithmSupported(publicKey, - kSecKeyOperationTypeEncrypt, - kSecKeyAlgorithmRSAEncryptionPKCS1); - if (canEncrypt) { - CFErrorRef error = NULL; - cipherText = (NSData *)CFBridgingRelease(SecKeyCreateEncryptedData(publicKey, - kSecKeyAlgorithmRSAEncryptionPKCS1, - (__bridge CFDataRef)data, - &error)); - if (!cipherText) { - NSError *err = CFBridgingRelease(error); - NSLog(@"%@", err); - } - } - }; - - if (self.keyTag) { - [self performWithPublicKeyTag:self.keyTag block:encryptor]; - } else { - encryptor(self.publicKeyRef); - } - - return cipherText; -} - -- (NSString *)decrypt64:(NSString*)message { - NSData *data = [[NSData alloc] initWithBase64EncodedString:message options:NSDataBase64DecodingIgnoreUnknownCharacters]; - NSData *decrypted = [self _decrypt: data]; - return [decrypted base64EncodedStringWithOptions:0]; -} - -- (NSString *)decrypt:(NSString *)message { - NSData *data = [[NSData alloc] initWithBase64EncodedString:message options:NSDataBase64DecodingIgnoreUnknownCharacters]; - NSData *decrypted = [self _decrypt: data]; - return [[NSString alloc] initWithData:decrypted encoding:NSUTF8StringEncoding]; -} - -- (NSData *)_decrypt:(NSData *)data { - __block NSData *clearText = nil; - - void(^decryptor)(SecKeyRef) = ^(SecKeyRef privateKey) { - - BOOL canDecrypt = SecKeyIsAlgorithmSupported(privateKey, - kSecKeyOperationTypeDecrypt, - kSecKeyAlgorithmRSAEncryptionPKCS1); - if (canDecrypt) { - CFErrorRef error = NULL; - clearText = (NSData *)CFBridgingRelease(SecKeyCreateDecryptedData(privateKey, - kSecKeyAlgorithmRSAEncryptionPKCS1, - (__bridge CFDataRef)data, - &error)); - if (!clearText) { - NSError *err = CFBridgingRelease(error); - NSLog(@"%@", err); - } - } - }; - - if (self.keyTag) { - [self performWithPrivateKeyTag:self.keyTag block:decryptor]; - } else { - decryptor(self.privateKeyRef); - } - - return clearText; -} - -- (NSString *)sign64:(NSString *)b64message withAlgorithm:(NSString *)algorithm { - NSData *data = [[NSData alloc] initWithBase64EncodedString:b64message options:NSDataBase64DecodingIgnoreUnknownCharacters]; - NSString *encodedSignature = [self _sign: data withAlgorithm:algorithm withEncodeOption: NSDataBase64Encoding64CharacterLineLength]; - return encodedSignature; -} - -- (NSString *)sign:(NSString *)message withAlgorithm:(NSString *)algorithm withEncodeOption: (NSDataBase64EncodingOptions)encodeOption{ - NSData* data = [message dataUsingEncoding:NSUTF8StringEncoding]; - NSString *encodedSignature = [self _sign: data withAlgorithm:algorithm withEncodeOption: encodeOption]; - return encodedSignature; -} - -- (NSString *)_sign:(NSData *)messageBytes withAlgorithm:(NSString *)signAlgorithm withEncodeOption: (NSDataBase64EncodingOptions)encodeOption { - __block NSString *encodedSignature = nil; - - void(^signer)(SecKeyRef) = ^(SecKeyRef privateKey) { - SecKeyAlgorithm algorithm; - if ([signAlgorithm isEqualToString: @"SHA512withRSA"]) { - algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512; - } else if ([signAlgorithm isEqualToString: @"SHA256withRSA"]) { - algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256; - } - - BOOL canSign = SecKeyIsAlgorithmSupported(privateKey, - kSecKeyOperationTypeSign, - algorithm); - - NSData* signature = nil; - - if (canSign) { - CFErrorRef error = NULL; - signature = (NSData*)CFBridgingRelease(SecKeyCreateSignature(privateKey, - algorithm, - (__bridge CFDataRef)messageBytes, - &error)); - if (!signature) { - NSError *err = CFBridgingRelease(error); - NSLog(@"error: %@", err); - } - } - - encodedSignature = [signature base64EncodedStringWithOptions: encodeOption]; - }; - - if (self.keyTag) { - [self performWithPrivateKeyTag:self.keyTag block:signer]; - } else { - signer(self.privateKeyRef); - } - - return encodedSignature; -} - -- (BOOL)verify64:(NSString *)encodedSignature withMessage:(NSString *)b64message withAlgorithm:(NSString *)verifyAlgorithm { - NSData *messageBytes = [[NSData alloc] initWithBase64EncodedString:b64message options:NSDataBase64DecodingIgnoreUnknownCharacters]; - NSData *signatureBytes = [[NSData alloc] initWithBase64EncodedString:encodedSignature options:NSDataBase64DecodingIgnoreUnknownCharacters]; - return [self _verify: signatureBytes withMessage: messageBytes withAlgorithm: verifyAlgorithm]; -} - -- (BOOL)verify:(NSString *)encodedSignature withMessage:(NSString *)message withAlgorithm:(NSString *)verifyAlgorithm { - NSData *messageBytes = [message dataUsingEncoding:NSUTF8StringEncoding]; - NSData *signatureBytes = [[NSData alloc] initWithBase64EncodedString:encodedSignature options:NSDataBase64DecodingIgnoreUnknownCharacters]; - return [self _verify: signatureBytes withMessage: messageBytes withAlgorithm: verifyAlgorithm]; -} - -- (BOOL)_verify:(NSData *)signatureBytes withMessage:(NSData *)messageBytes withAlgorithm:(NSString *)verifyAlgorithm { - __block BOOL result = NO; - - void(^verifier)(SecKeyRef) = ^(SecKeyRef publicKey) { - SecKeyAlgorithm algorithm; - if ([verifyAlgorithm isEqualToString: @"SHA512withRSA"]) { - algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA512; - } else if ([verifyAlgorithm isEqualToString: @"SHA256withRSA"]) { - algorithm = kSecKeyAlgorithmRSASignatureMessagePKCS1v15SHA256; - } - - BOOL canVerify = SecKeyIsAlgorithmSupported(publicKey, - kSecKeyOperationTypeVerify, - algorithm); - - if (canVerify) { - CFErrorRef error = NULL; - result = SecKeyVerifySignature(publicKey, - algorithm, - (__bridge CFDataRef)messageBytes, - (__bridge CFDataRef)signatureBytes, - &error); - if (!result) { - NSError *err = CFBridgingRelease(error); - NSLog(@"error: %@", err); - } - } - }; - - if (self.keyTag) { - [self performWithPublicKeyTag:self.keyTag block:verifier]; - } else { - verifier(self.publicKeyRef); - } - - return result; -} - -- (void)performWithPrivateKeyTag:(NSString *)keyTag block:(SecKeyPerformBlock)performBlock { - NSData *tag = [keyTag dataUsingEncoding:NSUTF8StringEncoding]; - NSDictionary *getquery = @{ (id)kSecClass: (id)kSecClassKey, - (id)kSecAttrApplicationTag: tag, - (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, - (id)kSecReturnRef: @YES, - }; - - SecKeyRef key = NULL; - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)getquery, - (CFTypeRef *)&key); - - if (status != errSecSuccess) { - NSLog(@"error accessing the key"); - } else { - if (performBlock) { performBlock(key); } - if (key) { CFRelease(key); } - } -} - -- (void)performWithPublicKeyTag:(NSString *)tag block:(SecKeyPerformBlock)performBlock { - [self performWithPrivateKeyTag:tag block:^(SecKeyRef key) { - SecKeyRef publicKey = SecKeyCopyPublicKey(key); - - if (performBlock) { performBlock(publicKey); } - if (publicKey) { CFRelease(publicKey); } - }]; -} - -- (NSString *) externalRepresentationForPublicKey:(SecKeyRef)key { - NSData *keyData = [self dataForKey:key]; - return [RSAFormatter PEMFormattedPublicKey:keyData]; -} - -- (NSString *) externalRepresentationForPrivateKey:(SecKeyRef)key { - NSData *keyData = [self dataForKey:key]; - return [RSAFormatter PEMFormattedPrivateKey:keyData]; -} - - -- (NSData *)dataForKey:(SecKeyRef)key { - CFErrorRef error = NULL; - NSData * keyData = (NSData *)CFBridgingRelease(SecKeyCopyExternalRepresentation(key, &error)); - - if (!keyData) { - NSError *err = CFBridgingRelease(error); - NSLog(@"%@", err); - } - - return keyData; -} - -@end diff --git a/react-native-rsa-native.podspec b/react-native-rsa-native.podspec index 3bda3f01..2b5f7fa0 100644 --- a/react-native-rsa-native.podspec +++ b/react-native-rsa-native.podspec @@ -12,8 +12,8 @@ Pod::Spec.new do |s| s.authors = package["author"]["name"] s.platforms = { :ios => "7.0", :tvos => "9.0" } s.source = { :git => package["repository"]["url"], :tag => "#{s.version}" } - s.source_files = "ios/**/*.{h,m}" - + s.source_files = "ios/**/*.{h,m,swift}" + s.swift_version = "4.2" s.dependency "React" end From 8d25d18e7e8627b8da895c0bfd0da305d0ac7cbd Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Wed, 22 Jan 2020 19:04:32 +0330 Subject: [PATCH 08/13] Fix verify --- ios/RSAECNative.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ios/RSAECNative.swift b/ios/RSAECNative.swift index b9bb1bb6..bb124adf 100644 --- a/ios/RSAECNative.swift +++ b/ios/RSAECNative.swift @@ -491,13 +491,13 @@ class RSAECNative: NSObject { public func verify64(encodedSignature: String, withMessage: String, withAlgorithm: String) -> Bool? { guard let messageBytes = Data(base64Encoded: encodedSignature, options: .ignoreUnknownCharacters) else { return nil } guard let signatureBytes = Data(base64Encoded: withMessage, options: .ignoreUnknownCharacters) else { return nil } - return self._verify(signatureBytes: messageBytes, withMessage: signatureBytes, withAlgorithm: withAlgorithm) + return self._verify(signatureBytes: signatureBytes, withMessage: messageBytes, withAlgorithm: withAlgorithm) } public func verify(encodedSignature: String, withMessage: String, withAlgorithm: String) -> Bool? { - guard let messageBytes = encodedSignature.data(using: .utf8) else { return nil } - guard let signatureBytes = Data(base64Encoded: withMessage, options: .ignoreUnknownCharacters) else { return nil } - return self._verify(signatureBytes: messageBytes, withMessage: signatureBytes, withAlgorithm: withAlgorithm) + guard let messageBytes = withMessage.data(using: .utf8) else { return nil } + guard let signatureBytes = Data(base64Encoded: encodedSignature, options: .ignoreUnknownCharacters) else { return nil } + return self._verify(signatureBytes:signatureBytes , withMessage: messageBytes, withAlgorithm: withAlgorithm) } private func _verify(signatureBytes: Data, withMessage: Data, withAlgorithm: String) -> Bool? { From 2072de855a3c5f760cf22a5fcfd57a886bb3983f Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Thu, 23 Jan 2020 10:49:35 +0330 Subject: [PATCH 09/13] Change default algorithm from sha1 to sha256 --- ios/RSAECNative.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/RSAECNative.swift b/ios/RSAECNative.swift index bb124adf..19d38538 100644 --- a/ios/RSAECNative.swift +++ b/ios/RSAECNative.swift @@ -21,7 +21,7 @@ class RSAECNative: NSObject { let publicKeyTag: String? let privateKeyTag: String? var publicKeyBits: Data? - var keyAlgorithm = KeyAlgorithm.rsa(signatureType: .sha1) + var keyAlgorithm = KeyAlgorithm.rsa(signatureType: .sha512) public init(keyTag: String?){ self.publicKeyTag = "\(keyTag ?? "").public" From 65dabd3af9c4cbd0462b4188f48535afa1a62e78 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Thu, 23 Jan 2020 10:50:16 +0330 Subject: [PATCH 10/13] Add sign and verify for RSA module --- ios/RNRSA.m | 9 +++++++ ios/RNRSA.swift | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/ios/RNRSA.m b/ios/RNRSA.m index 86303edf..dfaaeea0 100644 --- a/ios/RNRSA.m +++ b/ios/RNRSA.m @@ -16,14 +16,23 @@ @interface RCT_EXTERN_MODULE(RNRSA, NSObject) RCT_EXTERN_METHOD(generateKeys:(int)keySize resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(sign:(NSString *)message withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(signWithAlgorithm:(NSString *)message withKey:(NSString *)withKey withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(sign64:(NSString *)message withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(sign64WithAlgorithm:(NSString *)message withKey:(NSString *)withKey withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(verify:(NSString *)signature withMessage:(NSString *)withMessage withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(verifyWithAlgorithm:(NSString *)signature withMessage:(NSString *)withMessage withKey:(NSString *)withKey withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + +RCT_EXTERN_METHOD(verify64:(NSString *)signature withMessage:(NSString *)withMessage withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(verify64WithAlgorithm:(NSString *)signature withMessage:(NSString *)withMessage withKey:(NSString *)withKey withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) diff --git a/ios/RNRSA.swift b/ios/RNRSA.swift index bca21db6..49da4ddd 100644 --- a/ios/RNRSA.swift +++ b/ios/RNRSA.swift @@ -95,6 +95,21 @@ class RNRSA: NSObject { resolve(msg) } + @objc + func verify(_ signature: String, withMessage: String ,withKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPublicKey(publicKey: withKey) else { + resolve(false) + return + } + let signature = rsa_ec.verify(encodedSignature: signature, withMessage: withMessage, withAlgorithm: "SHA512withRSA") + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(true) + } + } + @objc func verifyWithAlgorithm(_ signature: String, withMessage: String ,withKey: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { let rsa_ec = RSAECNative() @@ -110,6 +125,22 @@ class RNRSA: NSObject { } } + + @objc + func verify64(_ signature: String, withMessage: String ,withKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPublicKey(publicKey: withKey) else { + resolve(false) + return + } + let signature = rsa_ec.verify64(encodedSignature: signature, withMessage: withMessage, withAlgorithm: "SHA512withRSA") + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(true) + } + } + @objc func verify64WithAlgorithm(_ signature: String, withMessage: String ,withKey: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { let rsa_ec = RSAECNative() @@ -125,6 +156,22 @@ class RNRSA: NSObject { } } + + @objc + func sign(_ message: String, withKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPrivateKey(privateKey: withKey) else { + resolve(false) + return + } + let signature = rsa_ec.sign(message: message, withAlgorithm: "SHA512withRSA", withEncodeOption: NSData.Base64EncodingOptions(rawValue: 0)) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(signature) + } + } + @objc func signWithAlgorithm(_ message: String, withKey: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { let rsa_ec = RSAECNative() @@ -140,6 +187,21 @@ class RNRSA: NSObject { } } + @objc + func sign64(_ message: String, withKey: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative() + guard let _ = rsa_ec.setPrivateKey(privateKey: withKey) else { + resolve(false) + return + } + let signature = rsa_ec.sign64(b64message: message, withAlgorithm: "SHA512withRSA") + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(signature) + } + } + @objc func sign64WithAlgorithm(_ message: String, withKey: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { let rsa_ec = RSAECNative() From 4ed0f1366aae9e71380a79e07926403b9df341b8 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Thu, 23 Jan 2020 10:50:30 +0330 Subject: [PATCH 11/13] Add sign and verify for RSAKeychain module --- ios/RNRSAKeychain.m | 8 ++++++++ ios/RNRSAKeychain.swift | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/ios/RNRSAKeychain.m b/ios/RNRSAKeychain.m index 14b83af5..d3b1df7e 100644 --- a/ios/RNRSAKeychain.m +++ b/ios/RNRSAKeychain.m @@ -20,8 +20,12 @@ @interface RCT_EXTERN_MODULE(RNRSAKeychain, NSObject) RCT_EXTERN_METHOD(generateEC:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(sign:(NSString *)message keyTag:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(signWithAlgorithm:(NSString *)message keyTag:(NSString *)keyTag withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(sign64:(NSString *)message keyTag:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(sign64WithAlgorithm:(NSString *)message keyTag:(NSString *)keyTag withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(getPublicKeyDER:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) @@ -30,8 +34,12 @@ @interface RCT_EXTERN_MODULE(RNRSAKeychain, NSObject) RCT_EXTERN_METHOD(getPublicKey:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(verify:(NSString *)signature withMessage:(NSString *)withMessage withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(verifyWithAlgorithm:(NSString *)signature withMessage:(NSString *)withMessage keyTag:(NSString *)keyTag withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +RCT_EXTERN_METHOD(verify64:(NSString *)signature withMessage:(NSString *)withMessage withKey:(NSString *)withKey resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) + RCT_EXTERN_METHOD(verify64WithAlgorithm:(NSString *)signature withMessage:(NSString *)withMessage keyTag:(NSString *)keyTag withAlgorithm:(NSString *)withAlgorithm resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) RCT_EXTERN_METHOD(deletePrivateKey:(NSString *)keyTag resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) diff --git a/ios/RNRSAKeychain.swift b/ios/RNRSAKeychain.swift index b3c80659..0fb98b3a 100644 --- a/ios/RNRSAKeychain.swift +++ b/ios/RNRSAKeychain.swift @@ -102,6 +102,17 @@ class RNRSAKeychain: NSObject { resolve(false) } + @objc + func sign(_ message: String, keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let signature = rsa_ec.sign(message: message, withAlgorithm: "SHA512withRSA", withEncodeOption: NSData.Base64EncodingOptions(rawValue: 0)) + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(signature) + } + } + @objc func signWithAlgorithm(_ message: String, keyTag: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { let rsa_ec = RSAECNative(keyTag: keyTag) @@ -113,6 +124,17 @@ class RNRSAKeychain: NSObject { } } + @objc + func sign64(_ message: String, keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let signature = rsa_ec.sign64(b64message: message, withAlgorithm: "SHA512withRSA") + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(signature) + } + } + @objc func sign64WithAlgorithm(_ message: String, keyTag: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { let rsa_ec = RSAECNative(keyTag: keyTag) @@ -163,6 +185,17 @@ class RNRSAKeychain: NSObject { } } + @objc + func verify(_ signature: String, withMessage: String ,keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let signature = rsa_ec.verify(encodedSignature: signature, withMessage: withMessage, withAlgorithm: "SHA512withRSA") + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(true) + } + } + @objc func verifyWithAlgorithm(_ signature: String, withMessage: String ,keyTag: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { let rsa_ec = RSAECNative(keyTag: keyTag) @@ -174,6 +207,17 @@ class RNRSAKeychain: NSObject { } } + @objc + func verify64(_ signature: String, withMessage: String ,keyTag: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { + let rsa_ec = RSAECNative(keyTag: keyTag) + let signature = rsa_ec.verify64(encodedSignature: signature, withMessage: withMessage, withAlgorithm: "SHA512withRSA") + if(signature == nil){ + reject("not sign it", "error", nil) + }else { + resolve(true) + } + } + @objc func verify64WithAlgorithm(_ signature: String, withMessage: String ,keyTag: String, withAlgorithm: String, resolver resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void { let rsa_ec = RSAECNative(keyTag: keyTag) From 72bd66d10b4dfa9cda3aac174243015f70a21dc9 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Thu, 23 Jan 2020 10:52:58 +0330 Subject: [PATCH 12/13] Add sign and verify function for declare module --- index.d.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/index.d.ts b/index.d.ts index 3216bd63..d2adc0e9 100644 --- a/index.d.ts +++ b/index.d.ts @@ -20,7 +20,7 @@ declare module 'react-native-rsa-native' { namespace RSA { - export function generate(keySize: number): Promise; + export function generate(): Promise; export function generateKeys(keySize: number): Promise; export function encrypt(data: string, key: string): Promise; export function decrypt(data: string, key: string): Promise; @@ -28,9 +28,11 @@ declare module 'react-native-rsa-native' { export function decrypt64(data: string, key: string): Promise; export function sign(data: string, key: string): Promise; export function signWithAlgorithm(data: string, key: string, signature?: TypeCrypto): Promise; + export function sign64(data: string, key: string): Promise; export function sign64WithAlgorithm(data: string, key: string, signature?: TypeCrypto): Promise; export function verify(data: string, secretToVerify: string, key: string): Promise; export function verifyWithAlgorithm(data: string, secretToVerify: string, key: string, signature?: TypeCrypto): Promise; + export function verify64(data: string, secretToVerify: string, key: string): Promise; export function verify64WithAlgorithm(data: string, secretToVerify: string, key: string, signature?: TypeCrypto): Promise; export const SHA256withRSA: string; export const SHA512withRSA: string; @@ -41,7 +43,9 @@ declare module 'react-native-rsa-native' { } namespace RSAKeychain { - export function generate(keyTag: string, keySize: number): Promise; + export function generate(keyTag: string): Promise; + export function generateEC(keyTag: string): Promise; + export function generateCSR(keyTag: string, CN: string, signature?: TypeCrypto): Promise; export function generateKeys(keyTag: string, keySize: number): Promise; export function generateCSRWithEC(cn: String,keyTag: string, keySize: number): Promise; export function deletePrivateKey(keyTag: string): Promise; @@ -56,6 +60,8 @@ declare module 'react-native-rsa-native' { export function verifyWithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: TypeCrypto): Promise; export function verify64WithAlgorithm(data: string, secretToVerify: string, keyTag: string, signature?: TypeCrypto): Promise; export function getPublicKey(keyTag: string): Promise; + export function getPublicKeyDER(keyTag: string): Promise; + export function getPublicKeyRSA(keyTag: string): Promise; export function deletePrivateKey(keyTag: string): Promise; export const SHA256withRSA: string; export const SHA512withRSA: string; From 34413e072b0a16b42f4d07ba718b0430ad6e5fa3 Mon Sep 17 00:00:00 2001 From: saeedkargosha Date: Thu, 23 Jan 2020 11:03:16 +0330 Subject: [PATCH 13/13] Fix export Constance ECDSA algorithm --- index.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.d.ts b/index.d.ts index d2adc0e9..935d9b29 100644 --- a/index.d.ts +++ b/index.d.ts @@ -14,9 +14,9 @@ declare module 'react-native-rsa-native' { 'SHA256withRSA'| 'SHA512withRSA'| 'SHA1withRSA'| - 'SHA256withEC'| - 'SHA512withEC'| - 'SHA1withEC' + 'SHA256withECDSA'| + 'SHA512withECDSA'| + 'SHA1withECDSA' namespace RSA { @@ -66,7 +66,7 @@ declare module 'react-native-rsa-native' { export const SHA256withRSA: string; export const SHA512withRSA: string; export const SHA1withRSA: string; - export const SHA256withECDSa: string; + export const SHA256withECDSA: string; export const SHA512withECDSA: string; export const SHA1withECDSA: string; }