Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(PureBasic) JWE using RSAES-OAEP and AES GCMThis example duplicates the example A.1 in RFC 7516 for JSON Web Encryption (JWE). Note: This example requires Chilkat v9.5.0.66 or greater.
IncludeFile "CkStringBuilder.pb" IncludeFile "CkJsonObject.pb" IncludeFile "CkJwe.pb" IncludeFile "CkPrivateKey.pb" IncludeFile "CkPublicKey.pb" Procedure ChilkatExample() ; This requires the Chilkat API to have been previously unlocked. ; See Global Unlock Sample for sample code. ; Note: This example requires Chilkat v9.5.0.66 or greater. success.i plaintext.s = "The true sign of intelligence is not knowledge but imagination." ; --------------------------------- ; A.1.1 JOSE Header ; First build the JWE Protected Header. ; We want to build this: {"alg":"RSA-OAEP","enc":"A256GCM"} jweProtHdr.i = CkJsonObject::ckCreate() If jweProtHdr.i = 0 Debug "Failed to create object." ProcedureReturn EndIf CkJsonObject::ckAppendString(jweProtHdr,"alg","RSA-OAEP") CkJsonObject::ckAppendString(jweProtHdr,"enc","A256GCM") Debug "JWE Protected Header: " + CkJsonObject::ckEmit(jweProtHdr) Debug "--" ; --------------------------------- ; A.1.2 Content Encryption Key ; Note: Chilkat automatically generates the random CEK internally. ; The application does not need to explicitly take this step. ; --------------------------------- ; A.1.3. Key Encryption ; The application should load an RSA private key from any format. ; However, the application does not need to explicitly construct the JWE Encrypted Key. ; Chilkat automatically does it internally. ; The design of the Chilkat JWE API is to allow the application to create the JWE ; after specifying the inputs. (This is in contrast to forcing the application developer ; to painstakingly go through each step of the JWE construction process.) ; The specific RSA key used in the A.1 example is the following JWK: sbJwk.i = CkStringBuilder::ckCreate() If sbJwk.i = 0 Debug "Failed to create object." ProcedureReturn EndIf CkStringBuilder::ckAppend(sbJwk,"{" + Chr(34) + "kty" + Chr(34) + ": " + Chr(34) + "RSA" + Chr(34) + ",") CkStringBuilder::ckAppend(sbJwk,Chr(34) + "n" + Chr(34) + ": " + Chr(34) + "oahUIoWw0K0usKNuOR6H4wkf4oBUXHTxRvgb48E-BVvxkeDNjbC4he8rUW") CkStringBuilder::ckAppend(sbJwk,"cJoZmds2h7M70imEVhRU5djINXtqllXI4DFqcI1DgjT9LewND8MW2Krf3S") CkStringBuilder::ckAppend(sbJwk,"psk_ZkoFnilakGygTwpZ3uesH-PFABNIUYpOiN15dsQRkgr0vEhxN92i2a") CkStringBuilder::ckAppend(sbJwk,"sbOenSZeyaxziK72UwxrrKoExv6kc5twXTq4h-QChLOln0_mtUZwfsRaMS") CkStringBuilder::ckAppend(sbJwk,"tPs6mS6XrgxnxbWhojf663tuEQueGC-FCMfra36C9knDFGzKsNa7LZK2dj") CkStringBuilder::ckAppend(sbJwk,"YgyD3JR_MB_4NUJW_TqOQtwHYbxevoJArm-L5StowjzGy-_bq6Gw" + Chr(34) + ",") CkStringBuilder::ckAppend(sbJwk,Chr(34) + "e" + Chr(34) + ": " + Chr(34) + "AQAB" + Chr(34) + ",") CkStringBuilder::ckAppend(sbJwk,Chr(34) + "d" + Chr(34) + ": " + Chr(34) + "kLdtIj6GbDks_ApCSTYQtelcNttlKiOyPzMrXHeI-yk1F7-kpDxY4-WY5N") CkStringBuilder::ckAppend(sbJwk,"WV5KntaEeXS1j82E375xxhWMHXyvjYecPT9fpwR_M9gV8n9Hrh2anTpTD9") CkStringBuilder::ckAppend(sbJwk,"3Dt62ypW3yDsJzBnTnrYu1iwWRgBKrEYY46qAZIrA2xAwnm2X7uGR1hghk") CkStringBuilder::ckAppend(sbJwk,"qDp0Vqj3kbSCz1XyfCs6_LehBwtxHIyh8Ripy40p24moOAbgxVw3rxT_vl") CkStringBuilder::ckAppend(sbJwk,"t3UVe4WO3JkJOzlpUf-KTVI2Ptgm-dARxTEtE-id-4OJr0h-K-VFs3VSnd") CkStringBuilder::ckAppend(sbJwk,"VTIznSxfyrj8ILL6MG_Uv8YAu7VILSB3lOW085-4qE3DzgrTjgyQ" + Chr(34) + ",") CkStringBuilder::ckAppend(sbJwk,Chr(34) + "p" + Chr(34) + ": " + Chr(34) + "1r52Xk46c-LsfB5P442p7atdPUrxQSy4mti_tZI3Mgf2EuFVbUoDBvaRQ-") CkStringBuilder::ckAppend(sbJwk,"SWxkbkmoEzL7JXroSBjSrK3YIQgYdMgyAEPTPjXv_hI2_1eTSPVZfzL0lf") CkStringBuilder::ckAppend(sbJwk,"fNn03IXqWF5MDFuoUYE0hzb2vhrlN_rKrbfDIwUbTrjjgieRbwC6Cl0" + Chr(34) + ",") CkStringBuilder::ckAppend(sbJwk,Chr(34) + "q" + Chr(34) + ": " + Chr(34) + "wLb35x7hmQWZsWJmB_vle87ihgZ19S8lBEROLIsZG4ayZVe9Hi9gDVCOBm") CkStringBuilder::ckAppend(sbJwk,"UDdaDYVTSNx_8Fyw1YYa9XGrGnDew00J28cRUoeBB_jKI1oma0Orv1T9aX") CkStringBuilder::ckAppend(sbJwk,"IWxKwd4gvxFImOWr3QRL9KEBRzk2RatUBnmDZJTIAfwTs0g68UZHvtc" + Chr(34) + ",") CkStringBuilder::ckAppend(sbJwk,Chr(34) + "dp" + Chr(34) + ": " + Chr(34) + "ZK-YwE7diUh0qR1tR7w8WHtolDx3MZ_OTowiFvgfeQ3SiresXjm9gZ5KL") CkStringBuilder::ckAppend(sbJwk,"hMXvo-uz-KUJWDxS5pFQ_M0evdo1dKiRTjVw_x4NyqyXPM5nULPkcpU827") CkStringBuilder::ckAppend(sbJwk,"rnpZzAJKpdhWAgqrXGKAECQH0Xt4taznjnd_zVpAmZZq60WPMBMfKcuE" + Chr(34) + ",") CkStringBuilder::ckAppend(sbJwk,Chr(34) + "dq" + Chr(34) + ": " + Chr(34) + "Dq0gfgJ1DdFGXiLvQEZnuKEN0UUmsJBxkjydc3j4ZYdBiMRAy86x0vHCj") CkStringBuilder::ckAppend(sbJwk,"ywcMlYYg4yoC4YZa9hNVcsjqA3FeiL19rk8g6Qn29Tt0cj8qqyFpz9vNDB") CkStringBuilder::ckAppend(sbJwk,"UfCAiJVeESOjJDZPYHdHY8v1b-o-Z2X5tvLx-TCekf7oxyeKDUqKWjis" + Chr(34) + ",") CkStringBuilder::ckAppend(sbJwk,Chr(34) + "qi" + Chr(34) + ": " + Chr(34) + "VIMpMYbPf47dT1w_zDUXfPimsSegnMOA1zTaX7aGk_8urY6R8-ZW1FxU7") CkStringBuilder::ckAppend(sbJwk,"AlWAyLWybqq6t16VFd7hQd0y6flUK4SlOydB61gwanOsXGOAOv82cHq0E3") CkStringBuilder::ckAppend(sbJwk,"eL4HrtZkUuKvnPrMnsUUFlfUdybVzxyjz9JF_XyaY14ardLSjf4L_FNY" + Chr(34) + "}") ; Load this JWK into a Chilkat private key object. rsaPrivKey.i = CkPrivateKey::ckCreate() If rsaPrivKey.i = 0 Debug "Failed to create object." ProcedureReturn EndIf success = CkPrivateKey::ckLoadJwk(rsaPrivKey,CkStringBuilder::ckGetAsString(sbJwk)) If success <> 1 Debug CkPrivateKey::ckLastErrorText(rsaPrivKey) CkJsonObject::ckDispose(jweProtHdr) CkStringBuilder::ckDispose(sbJwk) CkPrivateKey::ckDispose(rsaPrivKey) ProcedureReturn EndIf ; The public key is used to encrypt (i.e. create the JWE), ; and the private key is used to decrypt. ; The RSA public key is simply a subset of the private key. The RSA public key ; is composed of the "n" and "e" members shown above. These are also known as the ; modulus and exponent. ; We can simply get the public key object from the private key object rsaPubKey.i = CkPrivateKey::ckGetPublicKey(rsaPrivKey) ; --------------------------------- ; A.1.4. Initialization Vector ; Chilkat automatically generates the necessary random IV internally. ; The application does not need to do this explicitly. ; --------------------------------- ; A.1.5. Additional Authenticated Data ; The Additional Authenticated Data encryption parameter is ; ASCII(BASE64URL(UTF8(JWE Protected Header))). ; Again, Chilkat automatically takes care of this internally. ; The application does not need to explicitly take this step. ; --------------------------------- ; A.1.6. Content Encryption ; Again... this step is handled by Chilkat internally. ; --------------------------------- ; A.1.7. Complete Representation ; The application need only call the Encrypt, EncryptSb, or EncryptBd method ; return the fully assembled JWE. ; The final representation in the Compact Serialization ; is the string BASE64URL(UTF8(JWE Protected Header)) || '.' || ; BASE64URL(JWE Encrypted Key) || '.' || BASE64URL(JWE Initialization ; Vector) || '.' || BASE64URL(JWE Ciphertext) || '.' || BASE64URL(JWE ; Authentication Tag). jwe.i = CkJwe::ckCreate() If jwe.i = 0 Debug "Failed to create object." ProcedureReturn EndIf CkJwe::ckSetProtectedHeader(jwe,jweProtHdr) CkJwe::ckSetPublicKey(jwe,0,rsaPubKey) CkPublicKey::ckDispose(rsaPubKey) strJwe.s = CkJwe::ckEncrypt(jwe,plaintext,"utf-8") If CkJwe::ckLastMethodSuccess(jwe) <> 1 Debug CkJwe::ckLastErrorText(jwe) CkJsonObject::ckDispose(jweProtHdr) CkStringBuilder::ckDispose(sbJwk) CkPrivateKey::ckDispose(rsaPrivKey) CkJwe::ckDispose(jwe) ProcedureReturn EndIf ; Note: The RSA OAEP algorithm uses random padding bytes internally. ; Therefore, the results will appear different each time -- even if the ; identical plaintext is encrypted with the identical RSA key. ; (Do not expect the appearance of the results to be the same as what ; is published in the RFC. However, what is published in the RFC *should* ; be decryptable using the code that follows.) Debug strJwe ; Let's decrypt the JWE that was just produced. ; Do the following to decrypt a JWE: ; 1) Load the JWE. ; 2) Set the private key for decryption. ; 3) Decrypt. jwe2.i = CkJwe::ckCreate() If jwe2.i = 0 Debug "Failed to create object." ProcedureReturn EndIf success = CkJwe::ckLoadJwe(jwe2,strJwe) If success <> 1 Debug CkJwe::ckLastErrorText(jwe2) CkJsonObject::ckDispose(jweProtHdr) CkStringBuilder::ckDispose(sbJwk) CkPrivateKey::ckDispose(rsaPrivKey) CkJwe::ckDispose(jwe) CkJwe::ckDispose(jwe2) ProcedureReturn EndIf ; Provide the RSA private key for decryption. ; (The JWE was encrypted for a single recipient at index 0.) CkJwe::ckSetPrivateKey(jwe2,0,rsaPrivKey) ; Decrypt. originalPlaintext.s = CkJwe::ckDecrypt(jwe2,0,"utf-8") If CkJwe::ckLastMethodSuccess(jwe2) <> 1 Debug CkJwe::ckLastErrorText(jwe2) CkJsonObject::ckDispose(jweProtHdr) CkStringBuilder::ckDispose(sbJwk) CkPrivateKey::ckDispose(rsaPrivKey) CkJwe::ckDispose(jwe) CkJwe::ckDispose(jwe2) ProcedureReturn EndIf Debug "original text: " Debug originalPlaintext ; --------------------------------------------------------------------------------- ; It should also be possible to decrypt the JWE as shown in RFC 7516, Appendix A.1.7 ; because it was produced using the same RSA key. sbJwe.i = CkStringBuilder::ckCreate() If sbJwe.i = 0 Debug "Failed to create object." ProcedureReturn EndIf CkStringBuilder::ckAppend(sbJwe,"eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.") CkStringBuilder::ckAppend(sbJwe,"OKOawDo13gRp2ojaHV7LFpZcgV7T6DVZKTyKOMTYUmKoTCVJRgckCL9kiMT03JGe") CkStringBuilder::ckAppend(sbJwe,"ipsEdY3mx_etLbbWSrFr05kLzcSr4qKAq7YN7e9jwQRb23nfa6c9d-StnImGyFDb") CkStringBuilder::ckAppend(sbJwe,"Sv04uVuxIp5Zms1gNxKKK2Da14B8S4rzVRltdYwam_lDp5XnZAYpQdb76FdIKLaV") CkStringBuilder::ckAppend(sbJwe,"mqgfwX7XWRxv2322i-vDxRfqNzo_tETKzpVLzfiwQyeyPGLBIO56YJ7eObdv0je8") CkStringBuilder::ckAppend(sbJwe,"1860ppamavo35UgoRdbYaBcoh9QcfylQr66oc6vFWXRcZ_ZT2LawVCWTIy3brGPi") CkStringBuilder::ckAppend(sbJwe,"6UklfCpIMfIjf7iGdXKHzg.") CkStringBuilder::ckAppend(sbJwe,"48V1_ALb6US04U3b.") CkStringBuilder::ckAppend(sbJwe,"5eym8TW_c8SuK0ltJ3rpYIzOeDQz7TALvtu6UG9oMo4vpzs9tX_EFShS8iB7j6ji") CkStringBuilder::ckAppend(sbJwe,"SdiwkIr3ajwQzaBtQD_A.") CkStringBuilder::ckAppend(sbJwe,"XFBoMYUZodetZdvTiFvSkQ") success = CkJwe::ckLoadJweSb(jwe2,sbJwe) If success <> 1 Debug CkJwe::ckLastErrorText(jwe2) CkJsonObject::ckDispose(jweProtHdr) CkStringBuilder::ckDispose(sbJwk) CkPrivateKey::ckDispose(rsaPrivKey) CkJwe::ckDispose(jwe) CkJwe::ckDispose(jwe2) CkStringBuilder::ckDispose(sbJwe) ProcedureReturn EndIf ; Provide the RSA private key for decryption. CkJwe::ckSetPrivateKey(jwe2,0,rsaPrivKey) ; Decrypt. originalPlaintext = CkJwe::ckDecrypt(jwe2,0,"utf-8") If CkJwe::ckLastMethodSuccess(jwe2) <> 1 Debug CkJwe::ckLastErrorText(jwe2) CkJsonObject::ckDispose(jweProtHdr) CkStringBuilder::ckDispose(sbJwk) CkPrivateKey::ckDispose(rsaPrivKey) CkJwe::ckDispose(jwe) CkJwe::ckDispose(jwe2) CkStringBuilder::ckDispose(sbJwe) ProcedureReturn EndIf Debug originalPlaintext CkJsonObject::ckDispose(jweProtHdr) CkStringBuilder::ckDispose(sbJwk) CkPrivateKey::ckDispose(rsaPrivKey) CkJwe::ckDispose(jwe) CkJwe::ckDispose(jwe2) CkStringBuilder::ckDispose(sbJwe) ProcedureReturn EndProcedure |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.