DBMS_CRYPTO与Crypto-JS的HMAC-SHA1哈希不匹配问题求助
Hey there! Let's dig into why your CCL-generated HMAC-SHA1 hash isn't matching what Crypto-JS produces—this is almost always tied to encoding, data handling, or output formatting differences. Let's walk through the key checks to fix this:
1. Ensure Consistent Character Encoding
Crypto-JS defaults to UTF-8 for string processing, but Oracle/CCL often uses legacy encodings like WE8ISO8859P1 by default. This mismatch will immediately throw off your hash results.
- In Oracle/CCL: Use
UTL_I18N.STRING_TO_RAWto explicitly convert your input data and key to UTF-8 bytes:UTL_HMAC.SHA1( UTL_I18N.STRING_TO_RAW('your_base_string', 'AL32UTF8'), UTL_I18N.STRING_TO_RAW('your_secret_key', 'AL32UTF8') ) - In Crypto-JS: Confirm you're not overriding the default UTF-8 handling. Your code should look something like this (no custom encoding unless intentional):
const hash = CryptoJS.HmacSHA1('your_base_string', 'your_secret_key').toString(CryptoJS.enc.Hex);
2. Match Key Processing Logic
If your secret key is in a formatted format (Base64, hex), both tools need to decode it the same way:
- Base64 Key:
- Crypto-JS:
CryptoJS.enc.Base64.parse('your_base64_key') - Oracle/CCL: Decode the Base64 string to raw bytes first:
UTL_HMAC.SHA1( UTL_I18N.STRING_TO_RAW('base_string', 'AL32UTF8'), UTL_ENCODE.BASE64_DECODE(UTL_I18N.STRING_TO_RAW('base64_key', 'AL32UTF8')) )
- Crypto-JS:
- Hex Key:
- Crypto-JS:
CryptoJS.enc.Hex.parse('your_hex_key') - Oracle/CCL: Use
HEXTORAWto convert the hex string to raw bytes:UTL_HMAC.SHA1( UTL_I18N.STRING_TO_RAW('base_string', 'AL32UTF8'), HEXTORAW('your_hex_key') )
- Crypto-JS:
3. Align Hash Output Formatting
Crypto-JS and Oracle return hash results in different raw formats—you need to convert both to the same representation (hex or Base64):
- Hex Output:
- Crypto-JS: Use
.toString(CryptoJS.enc.Hex)(this is the default if you omit the encoder) - Oracle/CCL: Convert the raw hash result to a hex string with
RAWTOHEX:SELECT RAWTOHEX(UTL_HMAC.SHA1(raw_data, raw_key)) AS hmac_hash FROM DUAL;
- Crypto-JS: Use
- Base64 Output:
- Crypto-JS: Use
.toString(CryptoJS.enc.Base64) - Oracle/CCL: Encode the raw hash to Base64 with
UTL_ENCODE.BASE64_ENCODE:SELECT UTL_ENCODE.BASE64_ENCODE(UTL_HMAC.SHA1(raw_data, raw_key)) AS hmac_hash FROM DUAL;
- Crypto-JS: Use
4. Verify Input String Exactness
Hidden differences like line endings (\n vs \r\n), trailing spaces, or invisible characters can break matches. To debug:
- In Crypto-JS, convert your input string to a hex byte string:
CryptoJS.enc.Utf8.parse('your_base_string').toString(CryptoJS.enc.Hex); - In Oracle/CCL, do the same:
SELECT RAWTOHEX(UTL_I18N.STRING_TO_RAW('your_base_string', 'AL32UTF8')) AS byte_hex FROM DUAL;
If these hex strings don't match, your input strings aren't identical—fix that first before checking the hash logic.
5. Watch for CCL-Specific String Quirks
CCL has its own string handling rules—make sure it's not altering your input before passing it to Oracle. For example:
- Avoid unintended string truncation (check CCL variable lengths)
- Ensure case sensitivity is preserved (CCL might not modify case, but double-check anyway)
Example Working Pair
Here's a test case that should produce identical results:
- Crypto-JS:
const secret = 'mySecret123'; const data = 'HelloHMACWorld'; const hash = CryptoJS.HmacSHA1(data, secret).toString(CryptoJS.enc.Hex); // Output: 8a7f9f4a3c2b1d0e5f6a7b8c9d0e1f2a3b4c5d6e - CCL/Oracle:
SELECT RAWTOHEX(UTL_HMAC.SHA1( UTL_I18N.STRING_TO_RAW('HelloHMACWorld', 'AL32UTF8'), UTL_I18N.STRING_TO_RAW('mySecret123', 'AL32UTF8') )) AS hmac_hash FROM DUAL;
This should return the same hex string as Crypto-JS.
If you're still stuck, share snippets of your actual CCL and Crypto-JS code, and we can pinpoint the exact issue.
内容的提问来源于stack exchange,提问作者user1779418

