A Secret looks like a ConfigMap whose values are base64-encoded, plus a type that lets the API validate its keys: Opaque (anything), kubernetes.io/tls (TLS and Path Routing), kubernetes.io/dockerconfigjson for registry logins and kubernetes.io/service-account-token (Connecting Jenkins). Base64 exists so values can hold binary data; it is an encoding, not encryption:
kubectl create secret generic demo-secret --from-literal=password='s3cr3t!'
kubectl get secret demo-secret -o jsonpath='{.data.password}'; echo
kubectl get secret demo-secret -o jsonpath='{.data.password}' | base64 -d; echosecret/demo-secret created czNjcjN0IQ== s3cr3t!
Secrets are safer than ConfigMaps through handling, not encoding: the kubelet fetches a Secret only for Pods on its node that use it and keeps it on tmpfs, RBAC can grant ConfigMaps without Secrets, and encryption at rest (Encryption at Rest) covers them. The limits: list returns every value, so granting it grants all Secrets; anyone who can create a Pod in a namespace can mount its Secrets; and a Secret committed to Git 1,932 is plain text to every clone. stringData skips the manual encoding; keeping values out of Git is Secrets Management's topic.