簡體   English   中英

Java to Objective-C RSA實現

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM