In order to verify an RSA private key wrapping operation performed on a HSM, I try to decrypt it using Bouncy Castle. The private key is encrypted using an hybrid encryption scheme:
- A temporary AES session key is generated
- This session key is used to encrypt the target private using CKM_RSA_PKCS (for example) mechanism
- The session key is itself encrypted using a private master key stored in the HSM using CKM_AES_GCM mechanism.
The HSM returns the encrypted keys. As I have access to the software versions of the private master key and the on-the-fly generated AES key, I am able to decrypt the session key and verify that it is the expected one. Unfortunately, I cannot decrypt the wrapped private key with the session key and BC. It fails with the exception javax.crypto.AEADBadTagException: mac check in GCM failed.
This error seems to be related to the authenticated tag that is part of the returned cryptogram. Indeed, when I try to decrypt the private key ignoring the authentication, that is increasing the counter and using CKM_AES_CTR mechanism following Maarten Bodewes proposal I successfully get access to the private key.
Could someone help me to understand what I am doing wrong when decrypting?
Here is some information that could be useful:
- The HSM is an UTIMACO SecurityServer Simulator version 4.60.0.0
- The Java code used to decrypt is the following:
String secretKeyString = "BIh3JY8bSvmikYWOm1qk6w=="; SecretKey secretKey = new SecretKeySpec(Base64.decode(secretKeyString), "AES"); String iv = "6rLMygOozSqr7Zqx"; byte[] ivBytes = Base64.decode(iv); int TAG_SIZE = 128; String wrappedPrivateKey = "d107836481c54e6133435f57924c1197697fb3f82810c50bdeb9f30e7570929bc6e344e7a4a70092ee9ca4283d1f5ff35a4ffdc900e320448ebe9ef45dd7226632eb1a1c8437136113c14a45d63da57fb744ec1f84047bbb225d831b4651a4b358febf4a850fd9aa97dbcfef9f0bb2300a06ba034c19a46257d5f6f8d62a7071422a0ec2cf9ae876b3b2d67a313d2e40cbbc121c7ad680eb46283411a5ca6cb50d98495d10b31cc650165fbf09da5ccbdcf3befd056ef2b7a31954957bcb1f3466454551c8486517ce859ce5ea56740066dd4dd811c798b88b8f7403b9084f3ee95f22849baeb29b1b198ad504b1817b14abf48cf42e330f9e372fc79d9e3e91ffb35bfce942d61c91f7f2cd6793a0f530467d68a579c6cd3e8dd60173223215fa027a79212507c5adb819f5955d9608c59379477ef4f796d4f5a01c91118591f262a3fc827b802d179872f829cb16db92f7b62adfda9eb5abb09fe7d9e535e0688b93ab3f36c8b6f8833b75a7fa2f163cd7720826d20a5ffa1e207078591da68ca73f43412ce61c18d8d3f939dd60a9c55e4f5812d1726816b23f449286629e134384a400ea25516a3b596073ca4bdd90b23c046a1ecf9590a7160a951c058ab2aac9de34e0dc23076be29f5a8f492fab4513062d53846114194a5fc7daded8a320c4313e4621169db7c89786f21c97b1bbbaa30245258d8e0db76732b9ebff5d58dc59569a2f4f910fa776c36948d87e98fd6e8ebb692d64dd9a76413067f20c93541518bc78e52ac9002e1dfa4c97a5f59267c3d59ef2b14b5605fdb6a62a87c010ec34fa1785ab66ebccc802565ce749c2b2301fc4b4256ad04d9be4c35e79b8f1f5e38ecf8c58577d99f4db5ecc0c7c3064b53368082aea80129cf2c7fb046ec0efbe1c6be941d7c1243273e4f1627bf3560a71734c2fa0534f7614c2cb6d3c63380a832dbf281737a1b3713252a7e782bb8c29a749c3aee684cbde39ca38e4236ced283eaa7bc6ec04e1b18c9e928c0470bedaf6ca574c05a5db4b15632d36cbf6f7e0f5d1302a5612f07ffae90cf729debd9e6460020c0dc7eda9bc2799a894e89ac0e4ca6eda021836b976d4939c99405d68c1138a66e5dfcf2e856a9c68976131cd7913e7a830b3a54fe2e8c822732de2d730f8b346f01110d8d2e75b11bcb1443d587191db99e8120908623dd75e7dbaa5cadd59dcb0d64d948e6e7b7cfe569198ce0f372a8674a68833fbe94f17958daac3943cdf5bdcc3681b78d7003b24316f1ef0531a123387c8f6d549fc5b2d6a84bb354ba6d2cdb18bbcad120569a371a59d7c7433e8a5eab843c07fc9225b2bd1a036b009441ee4091af567fff7782855e5b74ff27ba44ac562208190b8b246da653a1d1599c2112f61e94a4375ab784fd8999495a6b5cea221d985b232dd090edeff7863bc3eb9541c8f0658458314f2058fcbb32a7e7bde30a2321f4c1d9c151e0defa67933a472a3de890aaacd988d8fc9df8c828d4d541c790b9420ae1ee99617e07c2579153c49b8fc7c5362c12452b315fc36d3846648b3e4453c2d5008f609056c3d8c05c37036d13f06f350bfe1bf24c1415c7d44da01e81ed1607f550c051dca73d2847c4c6511b6ff64dfeca6e002a4a9a5fdaf59cd576066fd838efe4fbbb6da3b467b23a63f254c310bc16f5cc93a7088da2b8d887ac809dbe2b90ac73959197a7dbd58a487bd72ae890f3550890c8d1835dfb00aaf2f634211d1dbf88ea6f9828c90b7015129011379d7a02031cdf44346c5b14703419a0a1931bf5175f11a9780c761c114ec1df048c79a3a702e9b71ae8a682c15404b53c9b145b1c75c3f5a911df617097ceaa5e62dc474861ef83cabcfbd950895b754985915651d6173b716fdd472464e2e507873b55871d06b05bfaa47818d551828219f58f314900185232fe07d24cabc081dfab150ef2f0497484a43c32260286ca5d3d121773d40c4abdef9a6bce42801b2707118b3c9812f54ee4aa113d8b2cf84c92e07714e2f362cb96e537814b17e8d4be13784c2af4534c19c15a0caf47ab98d974e228d5a0e42535029689bdb2f0946267e4056c498d6788297cba3b9b5336384072de8d65003eb59e7481755afde18a398ba1c60ebb18df1aa98f6ec49d573c7f3b10de6c59967528cc374abbd8fc26e96c37520019d648146c6f8c3f8f245d8a8d68f2e3381dfbe50186593c61a4b589991c76b72140e1501d4e5048cd0d19b0707bf638ce05c658292b8fa47a50daa62a675aa4201d4fe57677bc2361e0b292f0714ac898f86c166417027e76cee555b9dfe2cc4139d2fa01c3db8bfc39a9895f287e870460fd3ca1edbc9848982e6f6c65beaf28919c7f08e319f94f64d55faf8a5ba9aeb9b77490de9f145b66ced76e7d7c2e97e0bf5f6b141b312cc1aa7e396c865a0b19c4d827efb7f8e4d1db36a18cee51ee21d73159c6c7612550e6c084e489f2ceec43921392088bb5d2d086ab82a838136799c2879058fb93801bd3eb1d7b580cdccf790ba4f0842fab0b344a7569debae82e98acf"; final byte[] cryptogram = HexFormat.of().parseHex(wrappedPrivateKey); Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", BouncyCastleProvider.PROVIDER_NAME); final GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(TAG_SIZE, ivBytes); cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmParameterSpec); final byte[] bytes = cipher.doFinal(cryptogram);
Источник:
https://stackoverflow.com/questions/780 ... s-gcm-on-a