[英]Java to Objective-C RSA Implementation
我在Objective-C
中實現RSA encryption
和解密時遇到了麻煩,我在Java
非常簡單地實現了它,現在我嘗試在objc
轉換此java
代碼。 這是我的java
代碼:
public static byte[] encryptRSA(byte[] text, PublicKey key) throws Exception {
byte[] cipherText = null;
// get an RSA cipher object and print the provider
Cipher cipher = Cipher.getInstance("RSA");
// encrypt the plaintext using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
cipherText = cipher.doFinal(text);
return cipherText;
}
public static byte[] decryptRSA(byte[] text, PrivateKey key) throws Exception {
byte[] dectyptedText = null;
// decrypt the text using the private key
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
return dectyptedText;
}
這就是我生成密鑰對的方式
String seed = "SOMERANDOMSEED"+Long.toString(System.currentTimeMillis());
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
SecureRandom rand = new SecureRandom(seed.getBytes());
keyGen.initialize(4096,rand);
KeyPair keyPair = keyGen.generateKeyPair();
PrivateKey privateKey = keyPair.getPrivate();
PublicKey publicKey = keyPair.getPublic();
現在在objC中,我編寫了一些可以正常工作的代碼,但我不知道像從Java中那樣從種子生成rsa的方法很熱,以及如何使用此方法導入保存在Java中的密鑰
//for import
public static byte[] hexStringToByteArray(String s) {
byte[] b = new byte[s.length() / 2];
for (int i = 0; i < b.length; i++) {
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);
b[i] = (byte) v;
}
return b;
}
//for export
public static String byteArrayToHexString(byte[] b) {
StringBuilder sb = new StringBuilder(b.length * 2);
for (int i = 0; i < b.length; i++) {
int v = b[i] & 0xff;
if (v < 16) {
sb.append('0');
}
sb.append(Integer.toHexString(v));
}
return sb.toString().toUpperCase();
}
這是我的objc代碼
//this works properly
+(NSString *)decryptRSA:(NSString *)cipherString key:(SecKeyRef) privateKey {
size_t plainBufferSize = SecKeyGetBlockSize(privateKey);
uint8_t *plainBuffer = malloc(plainBufferSize);
NSData *incomingData = [cipherString decodeFromHexidecimal];
uint8_t *cipherBuffer = (uint8_t*)[incomingData bytes];
size_t cipherBufferSize = SecKeyGetBlockSize(privateKey);
SecKeyDecrypt(privateKey,
kSecPaddingOAEPKey,
cipherBuffer,
cipherBufferSize,
plainBuffer,
&plainBufferSize);
NSData *decryptedData = [NSData dataWithBytes:plainBuffer length:plainBufferSize];
NSString *decryptedString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
return decryptedString;
}
//this works properly
+(NSString *)encryptRSA:(NSString *)plainTextString key:(SecKeyRef)publicKey {
size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
uint8_t *cipherBuffer = malloc(cipherBufferSize);
uint8_t *nonce = (uint8_t *)[plainTextString UTF8String];
SecKeyEncrypt(publicKey,
kSecPaddingOAEPKey,
nonce,
strlen( (char*)nonce ),
&cipherBuffer[0],
&cipherBufferSize);
NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
return [encryptedData hexadecimalString];
}
//here i generate the key pair
#define kPublicKeyTag "com.apple.sample.publickey"
#define kPrivateKeyTag "com.apple.sample.privatekey"
//i should use these as seed!?!!?
- (void)generateKeyPair:(NSUInteger)keySize {
OSStatus sanityCheck = noErr;
publicKeyRef = NULL;
privateKeyRef = NULL;
// Container dictionaries.
NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init];
NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init];
NSMutableDictionary * keyPairAttr = [[NSMutableDictionary alloc] init];
// Set top level dictionary for the keypair.
[keyPairAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(id)kSecAttrKeySizeInBits];
// Set the private key dictionary.
[privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecAttrIsPermanent];
[privateKeyAttr setObject:privateTag forKey:(id)kSecAttrApplicationTag];
// See SecKey.h to set other flag values.
// Set the public key dictionary.
[publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecAttrIsPermanent];
[publicKeyAttr setObject:publicTag forKey:(id)kSecAttrApplicationTag];
// See SecKey.h to set other flag values.
// Set attributes to top level dictionary.
[keyPairAttr setObject:privateKeyAttr forKey:(id)@kSecPrivateKeyAttrs];
[keyPairAttr setObject:publicKeyAttr forKey:(id)@kSecPublicKeyAttrs];
// SecKeyGeneratePair returns the SecKeyRefs just for educational purposes.
sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef);
}
這是我用來導出objc中的鍵的方法,看來工作就像java方法一樣
+ (NSString *)fromPrivateKeyToString: (SecKeyRef) privateKey {
size_t pkeySize = SecKeyGetBlockSize(privateKey);
NSData* pkeyData = [NSData dataWithBytes:privateKey length:pkeySize];
NSString* pkeyString = [pkeyData hexadecimalString];
return pkeyString;
}
盡管並非不可能從種子創建相同的密鑰對,但是您需要確保RNG 和密鑰對生成完全相同。 此外,需要以相同的方式使用要放入發生器中的種子。 通常在創建RNG或密鑰對時都不會考慮兼容性。 實際上,默認的“ SHA1PRNG”甚至在Java版本之間都已更改,並且未描述該算法。
如果要使用相同的私鑰,則最好生成它並將其傳輸到其他運行時。 有多種方法,但是一種方法是使用(密碼)加密的PKCS#8或PKCS#12格式。 當然,密鑰或密碼需要保密,但是您的種子值也是如此。
有關更多信息,請參見此Q / A。 別忘了在那兒投票贊成這個問題並回答,我可以在crypto ::上使用更多觀點。
正如我在其他答案中所解釋的那樣,使用相同的PRNG值生成相同的密鑰對非常棘手。 但這似乎並不是您所追求的。 似乎您想使用自己的種子PRNG來生成密鑰對。
通常,Java中的默認SecureRandom
由操作系統播種。 您可以提供自己的隨機數生成器的想法是,例如,使用自己的熵池(例如,從硬件隨機數生成器),可能會獲得“更好”的結果。 但是,通常,由操作系統播種的默認Java PRNG將提供足夠的隨機性。
當您使用SecureRandom
類時,您將使用種子種子相對較弱的PRNG 取代由操作系統提供的種子。 currentTimeMilis
當然不會給您太多熵,並且密碼似乎是靜態的。 通常認為這不足以生成RSA密鑰對。
如果確實需要,可以向池中添加一些熵:
// create runtime default PRNG
SecureRandom rng = new SecureRandom();
// make sure that the rng is seeded by the operating system
rng.nextInt();
// add secret to the pool
rng.setSeed("SOME_SECRET".getBytes(StandardCharsets.UTF_8));
// add time information to the pool
rng.setSeed(System.currentTimeMillis());
// use for e.g. RSA key pair generation
似乎沒有辦法在Apple的OS X庫中注入您自己的隨機數生成器。 如圖所示,通常OS提供的隨機數生成器就足夠了。 如果確實需要,可以將其他種子寫入/dev/random
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.