Pre-shared keys are a fine way to learn IPsec and a poor way to run it. A PSK is a shared secret sitting in a config file, in plain sight of anyone with read access to the device, in your backup repository, and in the change ticket where someone pasted the running config. It does not scale either: with N peers you have N keys to distribute, and rotating one of them means touching both ends at the same time without dropping the tunnel.
Certificates fix both problems at once. Each device holds its own private key, which never leaves it, and a certificate signed by a common authority that every peer already trusts. Add a peer and you enroll it once; nobody else's config changes. Compromise a device and you revoke one certificate rather than rekeying a mesh. This article is the end-to-end walkthrough: build the trustpoint, authenticate the CA, enroll, and then bring up an IKEv2 tunnel with no pre-shared key anywhere in its configuration. It is the natural next step after the IPsec VPN guide, and it assumes you have a CA to enroll against.
We do. In the previous article we turned a cat8000v into a working IOS certificate authority called PLZ-CA. Everything below enrolls against that exact CA and uses the certificates it issued. All output is from the live lab.
The Trustpoint: Where Your Certificate Lives
A trustpoint is IOS's container for a certificate relationship. It holds the CA's certificate (so you can verify things the CA signed), your own identity certificate (so peers can verify you), the keypair backing that certificate, and the policy for how you got it and how you check it. One trustpoint, one CA relationship.
Here is GM1's, exactly as configured:
crypto key generate rsa modulus 2048 label PLZ-GM1-KEY
crypto pki trustpoint PLZ-TP
enrollment url http://10.100.0.31:80
subject-name CN=GM1.pinglabz.lab,O=PingLabz
revocation-check none
rsakeypair PLZ-GM1-KEY
Step 1: Authenticate the CA (and Actually Check the Fingerprint)
Before you can get a certificate, you have to decide you trust the entity that issues them. crypto pki authenticate fetches the CA's self-signed root certificate over SCEP and asks you a question. Here is the real exchange from GM1:
GM1(config)#crypto pki authenticate PLZ-TP
Certificate has the following attributes:
Fingerprint MD5: 50AE2189 0FC62684 1418DEF0 B0EB714A
Fingerprint SHA1: CAC64CCF 98899856 A5F002E5 C168BF80 0AB8355F
% Do you accept this certificate? [yes/no]: yes
Trustpoint CA certificate accepted.Now go and look at what the CA itself reported when we brought it up:
CA1#show crypto pki server
Certificate Server PLZ-CA:
Status: enabled
CA cert fingerprint: 50AE2189 0FC62684 1418DEF0 B0EB714ASame value. 50AE2189 0FC62684 1418DEF0 B0EB714A on the CA, and 50AE2189 0FC62684 1418DEF0 B0EB714A on the client. That match is not a curiosity. It is the entire security of this step, and it deserves a hard stare.
So IOS punts to the human. It prints the fingerprint of whatever certificate it just received and asks you to confirm. Your job, and this is the whole job, is to obtain the real CA's fingerprint through a channel the attacker does not control (an SSH session to the CA, a phone call to the person who runs it, a printed sheet in a binder) and compare it character by character. If they match, you are talking to the real CA. If they do not, you have just caught an attack.
If you type yes without doing that comparison, you have authenticated nothing. You have simply agreed to trust whatever answered. Every certificate that CA later signs, including the ones an attacker mints for himself, will validate perfectly on your router. The rest of your PKI is now theatre. This is a five-second check and skipping it invalidates everything downstream, so do not skip it.
Step 2: Enroll (Get Your Own Certificate)
With the CA trusted, ask it for an identity:
GM1(config)#crypto pki enroll PLZ-TPThis is also interactive: IOS asks for a challenge password (used for revocation requests later), whether to include the serial number and IP address in the subject, and whether to send the request now. The router then builds a CSR carrying your public key and subject name, signs it with your private key to prove you hold that key, and posts it to the enrollment URL. The private key itself never moves. The CA only ever sees the public half, which is the structural advantage over a PSK: no secret is ever in transit, and no secret ends up sitting in two config files at once.
Because our CA runs grant auto, it signs immediately and hands back the certificate. Syslog confirms:
%PKI-6-CERT_INSTALL: An ID certificate has been installedThe Certificate We Actually Got
Real output from GM1 after enrollment:
GM1#show crypto pki certificates PLZ-TP
Certificate
Status: Available
Certificate Serial Number (hex): 02
Certificate Usage: General Purpose
Issuer:
cn=PLZ-CA
o=PingLabz
c=US
Subject:
Name: GM1.pinglabz.lab
hostname=GM1.pinglabz.lab
cn=GM1.pinglabz.lab
o=PingLabz
Validity Date:
start date: 09:08:26 UTC Jul 13 2026
end date: 09:08:26 UTC Jul 12 2028
Associated Trustpoints: PLZ-TP
CA Certificate
Status: Available
Certificate Serial Number (hex): 01
Certificate Usage: Signature
Issuer:
cn=PLZ-CA
o=PingLabz
c=US
Subject:
cn=PLZ-CA
o=PingLabz
c=US
Validity Date:
start date: 09:04:14 UTC Jul 13 2026
end date: 09:04:14 UTC Jul 12 2031
Associated Trustpoints: PLZ-TPTwo certificates, and the difference between them is the whole of PKI.
The ID certificate (serial 02) is GM1's identity. Subject is cn=GM1.pinglabz.lab: this is who GM1 says it is. Issuer is cn=PLZ-CA: this is who vouches for that claim. Subject and Issuer are different, which is exactly what you expect from a certificate someone else signed. Validity runs two years, from Jul 13 2026 to Jul 12 2028, matching the CA's lifetime certificate 730. Usage is General Purpose, meaning it can be used for both signing and encryption.
The CA certificate (serial 01) is the trust anchor. Look closely: Subject and Issuer are identical, both cn=PLZ-CA. It signed itself, because there is nothing above it. Usage is Signature, because its job is to sign other certificates. Validity runs five years, out to 2031, comfortably outliving every certificate it will issue. GM1 holds this because you typed yes at the fingerprint prompt, and it is what GM1 will use to verify GM2's certificate later.
The Payoff: An IKEv2 Tunnel With No Pre-Shared Key
Now build a static VTI between GM1 and GM2 and authenticate it with those certificates:
crypto ikev2 proposal PLZ-CERT-PROP
encryption aes-cbc-256
integrity sha256
group 14
crypto ikev2 policy PLZ-CERT-POL
proposal PLZ-CERT-PROP
crypto ikev2 profile PLZ-CERT-PROF
match identity remote fqdn GM2.pinglabz.lab
identity local fqdn GM1.pinglabz.lab
authentication local rsa-sig
authentication remote rsa-sig
pki trustpoint PLZ-TP
crypto ipsec profile PLZ-CERT-IPSEC
set transform-set PLZ-CERT-TS
set ikev2-profile PLZ-CERT-PROF
interface Tunnel5
ip address 10.0.5.1 255.255.255.252
tunnel source GigabitEthernet2
tunnel mode ipsec ipv4
tunnel destination 10.100.0.22
tunnel protection ipsec profile PLZ-CERT-IPSECRead that config again and look for a secret. There is not one. No crypto isakmp key, no pre-shared-key local, no pre-shared-key remote, nothing. The three lines doing the work are:
authentication local rsa-sig- I will prove who I am by signing with my private key. Verify me against my certificate.authentication remote rsa-sig- I expect the peer to do the same. I will verify their signature against their certificate, and their certificate against the CA.pki trustpoint PLZ-TP- use this trustpoint for both. It holds my certificate and the CA certificate I need to check theirs.
The identity local and match identity remote lines are the identity contract, and they are about to cause us a problem.
The Failure We Hit: Identity Type Mismatch
The first time we brought this up, IKEv2 refused, with this:
IKEv2-ERROR:(SESSION ID = 1,SA ID = 1):: Auth exchange failedThat is the entire error. It tells you the authentication exchange failed, which you had already worked out, and nothing else. No mention of certificates, no mention of identities, no hint about which side had the problem. This message is the single most common thing you will see when certificate authentication goes wrong, and it is almost useless in isolation. Which is precisely why the pattern below is worth committing to memory.
The cause: we had configured identity local dn (send my identity as a Distinguished Name, taken from the certificate subject) while the peer's profile said match identity remote fqdn GM2.pinglabz.lab. So GM1 announced itself with a DN, and GM2's profile was looking for an FQDN. GM2 received a perfectly valid identity, in a perfectly valid certificate, signed by a CA it trusts, and rejected it because it was the wrong type of identity.
The fix took one line on each side:
crypto ikev2 profile PLZ-CERT-PROF
identity local fqdn GM1.pinglabz.labThe tunnel came up immediately.
When you see Auth exchange failed, check the identity types on both ends before anything else. The rule to internalize: the identity type you SEND must be the identity type the peer is told to MATCH. IKEv2 identities come in several flavours (fqdn, dn, address, email, key-id) and they are not interchangeable. If your side says identity local dn, the peer must say match identity remote dn ... with the full DN string. If your side says identity local fqdn GM1.pinglabz.lab, the peer must say match identity remote fqdn GM1.pinglabz.lab. Mixing the two produces a generic auth failure and hours of staring at crypto debugs.
The Proof: Auth sign RSA
With the identities aligned, here is the SA:
GM1#show crypto ikev2 sa detailed
Tunnel-id Local Remote fvrf/ivrf Status
1 10.100.0.21/500 10.100.0.22/500 none/none READY
Encr: AES-CBC, keysize: 256, PRF: SHA256, Hash: SHA256, DH Grp:14,
Auth sign: RSA, Auth verify: RSA
Local id: GM1.pinglabz.lab
Remote id: GM2.pinglabz.labAuth sign: RSA, Auth verify: RSA. On every pre-shared-key tunnel in this series, that field said PSK. Here it says RSA, twice: GM1 signed the IKE_AUTH exchange with its private key, and it verified GM2's signature using GM2's certificate, which it validated against the PLZ-CA certificate in its trustpoint.
Local id: GM1.pinglabz.lab and Remote id: GM2.pinglabz.lab are the identities that were exchanged and matched. Those strings came out of the certificates, and the certificates came out of a CA both routers independently decided to trust. No secret was ever shared between GM1 and GM2. They have still never held a key in common, and yet each one is certain of who it is talking to.
Revocation: Being Honest About It
Our trustpoint says revocation-check none. That means when GM1 validates GM2's certificate, it checks the signature and the validity dates, and stops. It does not ask whether the certificate has been revoked. If GM2 were compromised, its certificate torn up, and its revocation published to the world, GM1 would still cheerfully build a tunnel to it, right up until the certificate expired in 2028.
That is a real hole and it is on us. Here are the three options:
Use when: lab, or a closed environment where you can physically reach every device.
Cost: a revoked certificate stays usable until it expires. This is what we used, and we are telling you so.
Use when: you have a reliable CRL distribution point and can tolerate staleness.
Cost: a CRL is a snapshot. Revoke a certificate five minutes after the CRL was published and you are exposed until the next one. Also, if the CRL is unreachable, validation fails and your tunnels drop.
Use when: you want real-time revocation status and can run a highly available responder.
Cost: the responder is now in the path of every tunnel establishment. It must be up, and it must be fast.
For production, pick ocsp or crl based on what you can actually keep running, and think hard about whether a revocation check failure should drop tunnels (secure) or allow them (available). There is no free answer. What there definitely is not is a good reason to leave none on a production edge.
PSK vs Certificates
Certificates: enroll each device once against a common CA. Adding site 51 changes nothing on sites 1 through 50.
Certificates: the private key is generated on the device and never leaves it. Nothing secret is ever transmitted.
Certificates: re-enroll one device. Peers do not care, because they trust the CA, not the device.
Certificates: a compromised device exposes one private key. Revoke that certificate and it is over (assuming you actually check revocation).
Certificates: you now run a PKI. That means a CA, a clock, enrollment, expiry tracking, and revocation infrastructure. This is real, ongoing work.
Certificates: expired certificate, wrong clock, identity type mismatch, unreachable CRL. Errors are generic. You must know the patterns, which is why this article exists.
Key Takeaways
- A trustpoint holds one CA relationship: the enrollment URL, your subject name, your keypair, and the revocation policy. It says nothing about any peer or tunnel, which is exactly why it scales.
crypto pki authenticatedisplays the CA certificate's fingerprint and asks you to accept it. Compare that fingerprint out of band againstshow crypto pki serveron the CA. Ours matched at50AE2189 0FC62684 1418DEF0 B0EB714A. Typing yes without checking authenticates nothing.crypto pki enrollgenerates a CSR from your public key and subject name, sends it, and installs the returned identity certificate (%PKI-6-CERT_INSTALL). Your private key never leaves the router.- In
show crypto pki certificates, the ID certificate has different Subject and Issuer (GM1 signed by PLZ-CA, serial 02). The CA certificate has identical Subject and Issuer, because it signed itself (serial 01). - A certificate-authenticated IKEv2 tunnel uses
authentication local rsa-sig,authentication remote rsa-sig, andpki trustpoint. There is no pre-shared key anywhere in the configuration. Auth sign: RSA, Auth verify: RSAinshow crypto ikev2 sa detailedis the proof it worked. On a PSK tunnel that field says PSK.- Identity type mismatch is the number one cert-auth failure.
identity local dnagainstmatch identity remote fqdnproduces a bareAuth exchange failedand no other clue. The type you send must be the type the peer matches. - We used
revocation-check noneand are saying so plainly. Production wantscrlorocsp, and you need to decide deliberately whether a check failure should drop the tunnel or allow it.
The CA that issued these certificates is a plain IOS XE router, built from scratch in the same lab: see running a Cisco router as a CA server for how to stand one up in six lines. If the IKEv2 exchange itself is what you want to understand, IKEv2 explained covers the negotiation these certificates are plugged into, and the IPsec VPN pillar ties the whole progression together, from pre-shared keys through certificates to group encryption.