如何在Swift 3中使用带有Exponent和Modulus的RSA加密密码?

时间:2017-08-08 13:08:55

标签: ios swift encryption rsa

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

我有一个Exponent和一个Modulus(字符串中),那么如何使用这些值来加密我的密码呢?

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

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

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。

  1. 获取openssl
  2. pod 'OpenSSL-Universal'

    1. Basee64助手类
    2. 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
      
      1. 加密
      2. 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"

        1. 试一试
        2. PublicKeyRSA.encrypt(string, exponentB64: exponent, modulusB64: modulus)