xml加密解密

xml加密解密

使用python库xmlsec进行加密解密

流程

使用rsa cert将xml的特定element加密,加密后明文的element被EncryptData element代替, 解密的时候使用rsa cert对应的私钥进行解密.

代码

from os import path
import xmlsec
from lxml import etree

# Generating a self signed rsa cert run:
# openssl req  -nodes -new -x509  -keyout rsa.key -out rsa.cert

# rsa_cert is content of rsa.cert
rsa_cert = '''
-----BEGIN CERTIFICATE-----
MIICsDCCAhmgAwIBAgIJAIwKX7oCGsACMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTcwMzE2MDcwODEyWhcNMTcwNDE1MDcwODEyWjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQCo7z5I2ltfBmo++NUOHwtkyh4g8ORJ4imh9W3yh/8eE4ojaIminJ/Zd3+T8hqW
tmndOxtdmThZfXHhcscNRS/8zTsi97CaV0apkx93IVht8SCvb/MPd87tSIBuVbUa
JHzHvA9ah5z6TPtFFOf/tDQlJvAaJZgvkMjFlpD4nNiWNQIDAQABo4GnMIGkMB0G
A1UdDgQWBBR4dBejPLF7Yd94FI+YBDNveellZTB1BgNVHSMEbjBsgBR4dBejPLF7
Yd94FI+YBDNveellZaFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUt
U3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAIwKX7oC
GsACMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAkcAi44vq0pJLoZmd
v7odtGg5+aHnzY4BlHexj/zwuWFLt1r+GbK9sIp2tuuSn/Jbv5g8m25kDSc+xmVn
NdRo+wAnIdSX1dhXgsghM6Hog8h4wJDI1dS55xdJsIKCXbJdh6ECTvOoNT/p/q7v
YvfewGUx7p9C07TB+/do2J8Oln0=
-----END CERTIFICATE-----
'''

# content of rsa.key
rsa_private_key_pem = '''
-----BEGIN RSA PRIVATE KEY-----
MIICWwIBAAKBgQCo7z5I2ltfBmo++NUOHwtkyh4g8ORJ4imh9W3yh/8eE4ojaImi
nJ/Zd3+T8hqWtmndOxtdmThZfXHhcscNRS/8zTsi97CaV0apkx93IVht8SCvb/MP
d87tSIBuVbUaJHzHvA9ah5z6TPtFFOf/tDQlJvAaJZgvkMjFlpD4nNiWNQIDAQAB
AoGAVh2fIoQtD8O1ZWRzNz+cD0T5FtG1jfQ8RNNXuMqawjozsNkZUEuHMNQ5tLE1
3J4gWSZITO5OS1AnPUXFMn6SdvghPC9EKlqB+YwTdGUBWnNBP6sqUI/n7vHpE6+3
uTYuTo4Fvshau9gbfdEqNgYsuD5ibdjWNAQ+gCQuUvu/oAECQQDRMoyfdTu+sGwt
BHEtRqePZKBu/+uKz8SHRHWH2XAKfr0pIT+5innU1v3H5SEHqaU74evInzLBTFE3
mu/OsD9lAkEAzrqzJy/kvInTXDKPVEVF+oiqIIFlMjQiLmoHU6fbSEeRd80l+gPB
y9Mw48EZJ17dQiVh5MnO/6aY4wTQkyoWkQJAMW9vmbL7dll8hrrY/+kFabZOz0w8
3iWw/IIp//tbJa/DhbestmzJ04kmmZlEz+m/+UGvFU7BkLo3Kxu69a3inQJAbbtW
Sy+154n1IhRIVj/rFEAkpdppP8vCdQac2v/XerdadM/1H4+M98cjRVGDK43EPk8f
dlTUxojE0IQGvobxsQJAZ2Vabrbr+BUU7TkAJyGcBWLBYnD34PL9tD7sTM8jOFec
PVJJoLR12myTPUZaZG2GD2Fd9ruEcim78VJe0Z7E1A==
-----END RSA PRIVATE KEY-----
'''

doc_xml = '<?xml version="1.0" encoding="UTF-8"?><Envelope><Data>Hello, World!</Data></Envelope>'
root = etree.fromstring(doc_xml)

def encrypt_with_ras_cert():
    global root
    # Element to be encrypted
    data = root.find('./Data')
    # load key
    manager = xmlsec.KeysManager()
    key = xmlsec.Key.from_memory(rsa_cert, xmlsec.KeyFormat.CERT_PEM, None)
    manager.add_key(key)
    # Prepare for encryption
    enc_data = xmlsec.template.encrypted_data_create(
        root,
        xmlsec.Transform.AES128,
        type=xmlsec.EncryptionType.ELEMENT,
        ns='xenc'
    )
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_data)
    key_info = xmlsec.template.encrypted_data_ensure_key_info(enc_data, ns="dsig")
    enc_key = xmlsec.template.add_encrypted_key(key_info, xmlsec.Transform.RSA_OAEP)
    xmlsec.template.encrypted_data_ensure_cipher_value(enc_key)
    # Encrypt
    enc_ctx = xmlsec.EncryptionContext(manager)
    enc_ctx.key = xmlsec.Key.generate(xmlsec.KeyData.AES, 128, xmlsec.KeyDataType.SESSION)
    enc_ctx.encrypt_xml(enc_data, data)

def decrpyt_with_rsa_private_key():
    # find EncryptedData element
    global root
    enc_data = xmlsec.tree.find_child(root, "EncryptedData", xmlsec.Namespace.ENC)
    # load rsa private key
    dec_manager = xmlsec.KeysManager()
    dec_key = xmlsec.Key.from_memory(rsa_private_key_pem, xmlsec.KeyFormat.PEM, None)
    dec_manager.add_key(dec_key)
    dec_ctx = xmlsec.EncryptionContext(dec_manager)
    # Decrypt
    dec_ctx.decrypt(enc_data)

print '================= Original XML ======================\n'
print etree.tostring(root, pretty_print=True)
encrypt_with_ras_cert()
print '================= After Encrypted =====================\n'
print etree.tostring(root, pretty_print=True)
decrpyt_with_rsa_private_key()
print '================= After Decrypted =====================\n'
print etree.tostring(root, pretty_print=True)

输出:

================= Original XML ======================

<Envelope>
  <Data>Hello, World!</Data>
</Envelope>

================= After Encrypted =====================

<Envelope>
  <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Type="http://www.w3.org/2001/04/xmlenc#Element">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<xenc:EncryptedKey>
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"/>
<xenc:CipherData>
<xenc:CipherValue>bv37IOrVxNO8FE++8v0gBgmpbbUu6d5LRA/ZeGTH7Ga3f4POTJo1pZHq6dNhgG/H
NvBieVw8avX44TCBHNCqITMVJQJLIjFCNUkDKJFJ+obccCI9lcfvZkzZK5K62xmw
QvMIwkbY9lkdsqVz1EKWWPo64wijq/kJNJ7gApa/iGU=</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</dsig:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>Xgm7oR8KsgpSMTU5fQWiv7ECbjaEquel8z7dkjBURYTsWULjywwTfk/qyCNCCCCW</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</Envelope>

================= After Decrypted =====================

<Envelope>
  <Data>Hello, World!</Data>
</Envelope>

访问: