Example of implementing RSA encryption and SHA signature in java

Source: Internet
Author: User
Tags decrypt modulus openssl openssl rsa openssl x509 asymmetric encryption

I am happy to see this article. At that time, when I was doing RSA encryption and signature, the information on the Internet should not be too old. After that, I could not bear it anymore, this article will explain in detail how to implement RSA encryption and signature in iOS and fully synchronize with Java. This is my second blog. If you have any shortcomings, please advise.

What is RSA?

A: RSA is an asymmetric encryption algorithm. It is often used to encrypt transmitted data. It can be used together with the digest algorithm to sign text.

Padding in RSA encryption?

A: padding is the filling method. Because the plaintext to be encrypted in the RSA encryption algorithm is smaller than the modulus, padding restricts the length of the plaintext in some filling methods. We will introduce several padding modes and Segment encryption in detail later.

What is the difference between encryption and signature?

A: Encryption: The public key is placed on the client and the data is encrypted using the public key. After the server obtains the data, it uses the private key for decryption;

Signature: the private key is placed on the client, and the private key is used to sign the data. After the server obtains the data, it uses the public key for signature verification.

The former is completely encrypted; the latter is mainly used to prevent malicious attacks and prevent others from simulating our clients to attack our servers, resulting in server paralysis.

Basic principles

RSA uses a "Key pair" to encrypt and decrypt data. Before encryption and decryption, you need to save the Public Key and Private Key ).

Public key: used to encrypt data. Used to make Public. It is generally stored in the data provider, such as the iOS client.

Private key: used to decrypt data. It must be kept confidential. Private key leakage may cause security issues.

Security. framework in iOS provides support for the RSA algorithm. In this way, you need to process the key pair, generate a certificate based on the public key, and generate a key in p12 format through the private key. It's much easier to use strings for encryption and decryption in jave. (⊙ O ⊙ )...

 

Practice

Certificate generation

RSA encrypts the public key and private key. Apple does not support direct encryption and decryption using strings. We recommend that you use p12 files. Here we will teach you how to generate all the files used in encryption and provide them to Java. I thought this public key and private key had been around for a long time. % >_< %

 

Generate a private key with a modulo length of bits

Openssl genrsa-out private_key.pem 1024

Generate certification require file

Openssl req-new-key private_key.pem-out rsaCertReq. csr

Generate a certification and specify the Expiration Time

Openssl x509-req-days3650-in rsaCertReq. csr-signkey private_key.pem-out rsaCert. crt

Generate a public key for iOS

Openssl x509-outform der-in rsaCert. crt-out public_key.der

Generating a private key for iOS will allow you to enter the password, which will be used later when secKeyRef is generated

Openssl pkcs12-export-out private_key.p12-inkey private_key.pem-in rsaCert. crt

Generate the public key ending with pem for Java

Openssl rsa-in private_key.pem-out rsa_public_key.pem-pubout

Generate the private key ending with pem for Java to use openssl pkcs8-topk8-in private_key.pem-out pkcs8_private_key.pem-nocrypt

All the above steps are completed under the terminal (^__ ^)

SecKeyRef for generating public and private keys


// SecKeyRef corresponding to the private key generated based on your p12 file. If it is nil, check the steps for generating your p12 file.
-(SecKeyRef) getPrivateKeyRefrenceFromData :( NSData *) p12Data password :( NSString *) password {
SecKeyRef privateKeyRef = NULL;
NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
[Options setObject: password forKey :( _ bridge id) kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate (NULL, 0, 0, NULL );
OSStatus securityError = SecPKCS12Import (_ bridge CFDataRef) p12Data, (_ bridge CFDictionaryRef) options, & items );
If (securityError = noErr & CFArrayGetCount (items)> 0 ){
CFDictionaryRef identityDict = CFArrayGetValueAtIndex (items, 0 );
SecIdentityRef identityApp = (SecIdentityRef) CFDictionaryGetValue (identityDict, kSecImportItemIdentity );
SecurityError = SecIdentityCopyPrivateKey (identityApp, & privateKeyRef );
If (securityError! = NoErr ){
PrivateKeyRef = NULL;
    }
}
CFRelease (items );
Return privateKeyRef;
}
-
// SecKeyRef corresponding to the public key of your der file
-(SecKeyRef) getPublicKeyRefrenceFromeData: (NSData *) derData {
SecCertificateRef myCertificate = SecCertificateCreateWithData (kCFAllocatorDefault, (_ bridge CFDataRef) derData );
SecPolicyRef myPolicy = SecPolicyCreateBasicX509 ();
SecTrustRef myTrust;
OSStatus status = SecTrustCreateWithCertificates (myCertificate, myPolicy, & myTrust );
SecTrustResultType trustResult;
If (status = noErr ){
Status = SecTrustEvaluate (myTrust, & trustResult );
}
SecKeyRef securityKey = SecTrustCopyPublicKey (myTrust );
CFRelease (myCertificate );
CFRelease (myPolicy );
CFRelease (myTrust );
Return securityKey;
}
Encryption and decryption
-(NSData *) rsaEncryptData :( NSData *) data {
SecKeyRef key = [self getPublicKey];
Size_t cipherBufferSize = SecKeyGetBlockSize (key );
Uint8_t * cipherBuffer = malloc (cipherBufferSize * sizeof (uint8_t ));
Size_t blockSize = cipherBufferSize-11;
Size_t blockCount = (size_t) ceil ([data length]/(double) blockSize );
NSMutableData * encryptedData = [[NSMutableData alloc] init];
For (int I = 0; I <blockCount; I ++ ){
Unsigned long bufferSize = MIN (blockSize, [data length]-I * blockSize );
NSData * buffer = [data subdataWithRange: NSMakeRange (I * blockSize, bufferSize)];
OSStatus status = SecKeyEncrypt (key, kSecPaddingPKCS1, (const uint8_t *) [buffer bytes], [buffer length], cipherBuffer, & cipherBufferSize );
If (status! = NoErr ){
Return nil;
    }
NSData * encryptedBytes = [[NSData alloc] initWithBytes :( const void *) cipherBuffer length: cipherBufferSize];
[EncryptedData appendData: encryptedBytes];
    }
If (cipherBuffer ){
Free (cipherBuffer );
  }
Return encryptedData;
  }
-
-(NSData *) rsaDecryptData :( NSData *) data {
SecKeyRef key = [self getPrivatKey];
Size_t cipherBufferSize = SecKeyGetBlockSize (key );
Size_t blockSize = cipherBufferSize;
Size_t blockCount = (size_t) ceil ([data length]/(double) blockSize );
NSMutableData * decryptedData = [[NSMutableData alloc] init];
For (int I = 0; I <blockCount; I ++ ){
Unsigned long bufferSize = MIN (blockSize, [data length]-I * blockSize );
NSData * buffer = [data subdataWithRange: NSMakeRange (I * blockSize, bufferSize)];
Size_t cipherLen = [buffer length];
Void * cipher = malloc (cipherLen );
[Buffer getBytes: cipher length: cipherLen];
Size_t plainLen = SecKeyGetBlockSize (key );
Void * plain = malloc (plainLen );
OSStatus status = SecKeyDecrypt (key, kSecPaddingPKCS1, cipher, cipherLen, plain, & plainLen );
If (status! = NoErr ){
Return nil;
    }
NSData * decryptedBytes = [[NSData alloc] initWithBytes :( const void *) plain length: plainLen];
[DecryptedData appendData: decryptedBytes];
}
Return decryptedData;
}
Padding in RSA encryption

RSA_PKCS1_PADDING mode, the most common mode

Requirement: the input must be at least 11 bytes shorter than the RSA key modulo (modulus), that is, RSA_size (rsa)-11. If the input plaintext is too long, it must be cut and then filled.

Output: same length as modulus

According to this requirement, for a 1024/8-bit key, block length = 117-11 = bytes

 

RSA_PKCS1_OAEP_PADDING

Input: RSA_size (rsa)-41

Output: same length as modulus

 

RSA_NO_PADDING is not filled

Input: it can be as long as the RSA key modulo. If the input plaintext is too long, it must be cut and then filled

Output: same length as modulus

 

Signature and verification

// Sign the data with sha256

-(NSData *) rsaSHA256SignData :( NSData *) plainData {

SecKeyRef key = [self getPrivatKey];

 

Size_t signedHashBytesSize = SecKeyGetBlockSize (key );

Uint8_t * signedHashBytes = malloc (signedHashBytesSize );

Memset (signedHashBytes, 0x0, signedHashBytesSize );

 

Size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;

Uint8_t * hashBytes = malloc (hashBytesSize );

If (! CC_SHA256 ([plainData bytes], (CC_LONG) [plainData length], hashBytes )){

Return nil;

}

 

SecKeyRawSign (key,

KSecPaddingPKCS1SHA256,

HashBytes,

HashBytesSize,

SignedHashBytes,

& SignedHashBytesSize );

 

NSData * signedHash = [NSData dataWithBytes: signedHashBytes

Length :( NSUInteger) signedHashBytesSize];

 

If (hashBytes)

Free (hashBytes );

If (signedHashBytes)

Free (signedHashBytes );

 

Return signedHash;

    }

-

 

// If the signature data is successfully verified, YES is returned.

-(BOOL) rsaSHA256VerifyData :( NSData *) plainData withSignature :( NSData *) signature {

SecKeyRef key = [self getPublicKey];

 

Size_t signedHashBytesSize = SecKeyGetBlockSize (key );

Const void * signedHashBytes = [signature bytes];

 

Size_t hashBytesSize = CC_SHA256_DIGEST_LENGTH;

Uint8_t * hashBytes = malloc (hashBytesSize );

If (! CC_SHA256 ([plainData bytes], (CC_LONG) [plainData length], hashBytes )){

Return NO;

    }

 

OSStatus status = SecKeyRawVerify (key,

KSecPaddingPKCS1SHA256,

HashBytes,

HashBytesSize,

SignedHashBytes,

SignedHashBytesSize );

 

Return status = errSecSuccess;

    }

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.