ios - 如何在 Swift 3 中使用带有指数和模数的 RSA 来加密密码?

标签 ios swift encryption rsa

如何在 Swift 3 中使用带有指数和模数的 RSA 来加密密码?

我有一个指数和一个模数(字符串形式),那么如何使用这些值来加密我的密码?

"modulus" : "AI8W0a1hVzDphH0J8Q2tz64Y4UWNNqdUdck3RJrl3V8RYSaxW1lwBos77LNsXU13OcOpgB\/TfeefRBl0J2Dv\/8IwmBZC1M5ZGUfcq0JuogggRWro72WLCuIDPUGH9fO8D\/klAdVDFjVz6LnkWvCoX5WGE1OSygKqAPBO\/BWIRt4l",
"exponent" : "AQAB"

我找到了一些框架,但我没有任何 pem 文件可提供。

最佳答案

我找到了解决方案。

  1. 获取 openssl

pod 'OpenSSL-Universal'

  • Basee64 辅助类
  • NSData+TheBase64.h:

    #import <Foundation/Foundation.h>

    void *NewBase64Decode(const char *inputBuffer, size_t length, size_t *outputLength);
    char *NewBase64Encode(const void *inputBuffer, size_t length, bool separateLines, size_t *outputLength);
    
    @interface NSData (TheBase64)
    
    + (NSData *)dataFromBase64String:(NSString *)aString;
    - (NSString *)base64EncodedString;
    
    @end
    

    NSData+TheBase64.m:

    #import "NSData+TheBase64.h"
    
    //
    // Mapping from 6 bit pattern to ASCII character.
    //
    static unsigned char kBase64EncodeLookup[65] =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
    //
    // Definition for "masked-out" areas of the base64DecodeLookup mapping
    //
    #define xx 65
    
    //
    // Mapping from ASCII character to 6 bit pattern.
    //
    static unsigned char kBase64DecodeLookup[256] =
    {
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63, 
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx, 
        xx,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 
        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx, 
        xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 
        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
        xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 
    };
    
    //
    // Fundamental sizes of the binary and base64 encode/decode units in bytes
    //
    #define BINARY_UNIT_SIZE 3
    #define BASE64_UNIT_SIZE 4
    
    //
    // NewBase64Decode
    //
    // Decodes the base64 ASCII string in the inputBuffer to a newly malloced
    // output buffer.
    //
    //  inputBuffer - the source ASCII string for the decode
    //  length - the length of the string or -1 (to specify strlen should be used)
    //  outputLength - if not-NULL, on output will contain the decoded length
    //
    // returns the decoded buffer. Must be free'd by caller. Length is given by
    //  outputLength.
    //
    void *NewBase64Decode(
        const char *inputBuffer,
        size_t length,
        size_t *outputLength)
    {
        if (length == -1)
        {
            length = strlen(inputBuffer);
        }
    
        size_t outputBufferSize =
            ((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;
        unsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize);
    
        size_t i = 0;
        size_t j = 0;
        while (i < length)
        {
            //
            // Accumulate 4 valid characters (ignore everything else)
            //
            unsigned char accumulated[BASE64_UNIT_SIZE];
            size_t accumulateIndex = 0;
            while (i < length)
            {
                unsigned char decode = kBase64DecodeLookup[inputBuffer[i++]];
                if (decode != xx)
                {
                    accumulated[accumulateIndex] = decode;
                    accumulateIndex++;
    
                    if (accumulateIndex == BASE64_UNIT_SIZE)
                    {
                        break;
                    }
                }
            }
    
            //
            // Store the 6 bits from each of the 4 characters as 3 bytes
            //
            // (Uses improved bounds checking suggested by Alexandre Colucci)
            //
            if(accumulateIndex >= 2)  
                outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);  
            if(accumulateIndex >= 3)  
                outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);  
            if(accumulateIndex >= 4)  
                outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];
            j += accumulateIndex - 1;
        }
    
        if (outputLength)
        {
            *outputLength = j;
        }
        return outputBuffer;
    }
    
    //
    // NewBase64Encode
    //
    // Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced
    // output buffer.
    //
    //  inputBuffer - the source data for the encode
    //  length - the length of the input in bytes
    //  separateLines - if zero, no CR/LF characters will be added. Otherwise
    //      a CR/LF pair will be added every 64 encoded chars.
    //  outputLength - if not-NULL, on output will contain the encoded length
    //      (not including terminating 0 char)
    //
    // returns the encoded buffer. Must be free'd by caller. Length is given by
    //  outputLength.
    //
    char *NewBase64Encode(
        const void *buffer,
        size_t length,
        bool separateLines,
        size_t *outputLength) {
        const unsigned char *inputBuffer = (const unsigned char *)buffer;
    
        #define MAX_NUM_PADDING_CHARS 2
        #define OUTPUT_LINE_LENGTH 64
        #define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE)
        #define CR_LF_SIZE 2
    
        //
        // Byte accurate calculation of final buffer size
        //
        size_t outputBufferSize =
                ((length / BINARY_UNIT_SIZE)
                    + ((length % BINARY_UNIT_SIZE) ? 1 : 0))
                        * BASE64_UNIT_SIZE;
        if (separateLines) {
            outputBufferSize +=
                (outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;
        }
    
        //
        // Include space for a terminating zero
        //
        outputBufferSize += 1;
    
        //
        // Allocate the output buffer
        //
        char *outputBuffer = (char *)malloc(outputBufferSize);
        if (!outputBuffer) {
            return NULL;
        }
    
        size_t i = 0;
        size_t j = 0;
        const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;
        size_t lineEnd = lineLength;
    
        while (true) {
            if (lineEnd > length) {
                lineEnd = length;
            }
    
            for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE) {
                //
                // Inner loop: turn 48 bytes into 64 base64 characters
                //
                outputBuffer[j++] = kBase64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
                outputBuffer[j++] = kBase64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
                    | ((inputBuffer[i + 1] & 0xF0) >> 4)];
                outputBuffer[j++] = kBase64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)
                    | ((inputBuffer[i + 2] & 0xC0) >> 6)];
                outputBuffer[j++] = kBase64EncodeLookup[inputBuffer[i + 2] & 0x3F];
            }
    
            if (lineEnd == length) {
                break;
            }
    
            //
            // Add the newline
            //
            outputBuffer[j++] = '\r';
            outputBuffer[j++] = '\n';
            lineEnd += lineLength;
        }
    
        if (i + 1 < length) {
            //
            // Handle the single '=' case
            //
            outputBuffer[j++] = kBase64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
            outputBuffer[j++] = kBase64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
                | ((inputBuffer[i + 1] & 0xF0) >> 4)];
            outputBuffer[j++] = kBase64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];
            outputBuffer[j++] = '=';
        } else if (i < length) {
            //
            // Handle the double '=' case
            //
            outputBuffer[j++] = kBase64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
            outputBuffer[j++] = kBase64EncodeLookup[(inputBuffer[i] & 0x03) << 4];
            outputBuffer[j++] = '=';
            outputBuffer[j++] = '=';
        }
        outputBuffer[j] = 0;
    
        //
        // Set the output length and return the buffer
        //
        if (outputLength) {
            *outputLength = j;
        }
        return outputBuffer;
    }
    
    @implementation NSData (TheBase64)
    
    //
    // dataFromBase64String:
    //
    // Creates an NSData object containing the base64 decoded representation of
    // the base64 string 'aString'
    //
    // Parameters:
    //    aString - the base64 string to decode
    //
    // returns the autoreleased NSData representation of the base64 string
    //
    + (NSData *)dataFromBase64String:(NSString *)aString {
        NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding];
        size_t outputLength;
        void *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength);
        NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength];
        free(outputBuffer);
        return result;
    }
    
    //
    // base64EncodedString
    //
    // Creates an NSString object that contains the base 64 encoding of the
    // receiver's data. Lines are broken at 64 characters long.
    //
    // returns an autoreleased NSString being the base 64 representation of the
    //  receiver.
    //
    - (NSString *)base64EncodedString {
        size_t outputLength;
        char *outputBuffer =
            NewBase64Encode([self bytes], [self length], true, &outputLength);
    
        NSString *result =
            [[NSString alloc] initWithBytes:outputBuffer length:outputLength encoding:NSASCIIStringEncoding];
        free(outputBuffer);
        return result;
    }
    
    @end
    
  • 加密
  • PublicKeyRSA.h:

    #import <Foundation/Foundation.h>
    #import <OpenSSL/rsa.h>
    #import "NSData+TheBase64.h"
    
    @interface PublicKeyRSA : NSObject
    //+ (RSA * __nullable)rsaFromExponent:(NSString * __nonnull)exponent modulus:(NSString * __nonnull)modulus;
    //+ (NSString * __nullable)cleanString:(NSString * __nonnull)input;
    + (NSString * __nullable)encrypt:(NSString * __nonnull)string exponentB64:(NSString * __nonnull)exponentB64 modulusB64:(NSString * __nonnull)modulusB64;
    @end
    

    PublicKeyRSA.m:

    #import "PublicKeyRSA.h"
    
    @implementation PublicKeyRSA
    
    + (RSA *)rsaFromExponent:(NSString *)exponent modulus:(NSString *)modulus {
        RSA *rsa_pub = RSA_new();
    
        const char *N = [modulus UTF8String];
        const char *E = [exponent UTF8String];
    
        if (!BN_hex2bn(&rsa_pub->n, N))
        {
            // TODO
        }
        printf("N: %s\n", N);
        printf("n: %s\n", BN_bn2dec(rsa_pub->n));
    
        if (!BN_hex2bn(&rsa_pub->e, E))
        {
            // TODO
        }
        printf("E: %s\n", E);
        printf("e: %s\n", BN_bn2dec(rsa_pub->e));
    
        return rsa_pub;
    }
    
    + (NSString *)cleanString:(NSString *)input {
        NSString *output = input;
        output = [output stringByReplacingOccurrencesOfString:@"<" withString:@""];
        output = [output stringByReplacingOccurrencesOfString:@">" withString:@""];
        output = [output stringByReplacingOccurrencesOfString:@" " withString:@""];
        return output;
    }
    
    + (NSString *)encrypt:(NSString *)string exponentB64:(NSString *)exponentB64 modulusB64:(NSString *)modulusB64 {
    
        // 1. decode base64
        NSData *exponent = [NSData dataFromBase64String:exponentB64];
        NSData *modulus = [NSData dataFromBase64String:modulusB64];
    
        NSString *exponentHex = [self cleanString:[exponent description]];
        NSString *modulusHex = [self cleanString:[modulus description]];
    
        // 2. create RSA public key
        RSA *rsa_pub = [self rsaFromExponent:exponentHex modulus:modulusHex];
    
        // 3. encode base 64
        NSData *data = [string dataUsingEncoding: NSASCIIStringEncoding];
        NSString *b64String = [data base64EncodedString];
    
        // 4. encrypt
        const unsigned char *from = (const unsigned char *)[b64String cStringUsingEncoding: NSASCIIStringEncoding];
        int flen = strlen((const char *)from);
        unsigned char *to = (unsigned char *) malloc(RSA_size(rsa_pub));
        int padding = RSA_PKCS1_PADDING;
        int result = RSA_public_encrypt(flen, from, to, rsa_pub, padding);
        if (-1 == result) {
            return nil;
        }
    //        NSLog(@"from: %s", from); // echo VEVTVA==
    //        NSLog(@"to: %s", to); // echo something strange with characters like: ~™Ÿû—...
        // 5. encode base 64
        NSData *cipherData = [NSData dataWithBytes:(const void *)to length:result];
        NSString *cipherDataB64 = [cipherData base64EncodedString];
        NSLog(@"user encrypted b64: %@", cipherDataB64); // now echo the expected value
        return  cipherDataB64;
    }
    
    @end
    

    4.创建桥接头文件 Bridging-Header 并导入 <OpenSSL/rsa.h>"PublicKeyRSA.h""NSData+TheBase64.h"

  • 尝试一下
  • PublicKeyRSA.encrypt(string, exponentB64: exponent, modulusB64: modulus)

    关于ios - 如何在 Swift 3 中使用带有指数和模数的 RSA 来加密密码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45569250/

    相关文章:

    ios - 将 UIViewController 更改为 UITableViewController

    Swift - 如何重写 init 函数? (是 Objective-C 中的一个类别)

    ios - NSDate 作为 Swift 中的函数参数

    arrays - Swift:检查数组的字典对象类型

    ios - 如何处理SwiftUI中的水龙头开始

    security - 基于NTAG213和Ultralight C的支付应用程序(使用Android NFC)

    python - 将加密 key 存储为环境变量是个好主意吗?

    php - 如何加密 PHP 变量(链接)?

    ios - 获取 UIWebView 网址! (myWebView.request.URL.absoluteString 不工作)

    ios - Swift:将 View Controller 的类型更改为 UIViewController 以外的类型