diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## 1.0.3
+
+* Make sign of Ed25519/Ed448 safer. The public key parameter is
+  ignored and its public key is generated from the secret key
+  parameter to prevent Double Public Key Signing Function Oracle
+  Attack.
+  [#47](https://github.com/kazu-yamamoto/crypton/pull/47)
+
 ## 1.0.2
 
 * Deterministic Nonce Generation for ECDSA
diff --git a/Crypto/PubKey/Ed25519.hs b/Crypto/PubKey/Ed25519.hs
--- a/Crypto/PubKey/Ed25519.hs
+++ b/Crypto/PubKey/Ed25519.hs
@@ -27,6 +27,7 @@
     -- * Methods
     toPublic,
     sign,
+    unsafeSign,
     verify,
     generateSecretKey,
 ) where
@@ -100,9 +101,28 @@
             ccrypton_ed25519_publickey psec result
 {-# NOINLINE toPublic #-}
 
--- | Sign a message using the key pair
+-- | Sign a message using the key pair.
+--   The public key parameter is ignored and its public key
+--   is generated from the secret key parameter to prevent
+--   Double Public Key Signing Function Oracle Attack.
 sign :: ByteArrayAccess ba => SecretKey -> PublicKey -> ba -> Signature
-sign secret public message =
+sign secret _public message =
+    Signature $ B.allocAndFreeze signatureSize $ \sig ->
+        withByteArray secret $ \sec ->
+            withByteArray public $ \pub ->
+                withByteArray message $ \msg ->
+                    ccrypton_ed25519_sign msg (fromIntegral msgLen) sec pub sig
+  where
+    !msgLen = B.length message
+    public = toPublic secret
+
+-- | Sign a message using the key pair.  This is old `sign`, which is
+-- vulnerable to private key compromise if the given public key does
+-- not correspond to the secret key. This function is provided for
+-- performance critical applications. To use it safely, applications
+-- must verify or derive the public key.
+unsafeSign :: ByteArrayAccess ba => SecretKey -> PublicKey -> ba -> Signature
+unsafeSign secret public message =
     Signature $ B.allocAndFreeze signatureSize $ \sig ->
         withByteArray secret $ \sec ->
             withByteArray public $ \pub ->
diff --git a/Crypto/PubKey/Ed448.hs b/Crypto/PubKey/Ed448.hs
--- a/Crypto/PubKey/Ed448.hs
+++ b/Crypto/PubKey/Ed448.hs
@@ -31,6 +31,7 @@
     -- * Methods
     toPublic,
     sign,
+    unsafeSign,
     verify,
     generateSecretKey,
 ) where
@@ -105,8 +106,27 @@
 {-# NOINLINE toPublic #-}
 
 -- | Sign a message using the key pair
+--   The public key parameter is ignored and its public key
+--   is generated from the secret key parameter to prevent
+--   Double Public Key Signing Function Oracle Attack.
 sign :: ByteArrayAccess ba => SecretKey -> PublicKey -> ba -> Signature
-sign secret public message =
+sign secret _public message =
+    Signature $ B.allocAndFreeze signatureSize $ \sig ->
+        withByteArray secret $ \sec ->
+            withByteArray public $ \pub ->
+                withByteArray message $ \msg ->
+                    decaf_ed448_sign sig sec pub msg (fromIntegral msgLen) 0 no_context 0
+  where
+    !msgLen = B.length message
+    public = toPublic secret
+
+-- | Sign a message using the key pair.  This is old `sign`, which is
+-- vulnerable to private key compromise if the given public key does
+-- not correspond to the secret key. This function is provided for
+-- performance critical applications. To use it safely, applications
+-- must verify or derive the public key.
+unsafeSign :: ByteArrayAccess ba => SecretKey -> PublicKey -> ba -> Signature
+unsafeSign secret public message =
     Signature $ B.allocAndFreeze signatureSize $ \sig ->
         withByteArray secret $ \sec ->
             withByteArray public $ \pub ->
diff --git a/crypton.cabal b/crypton.cabal
--- a/crypton.cabal
+++ b/crypton.cabal
@@ -1,6 +1,6 @@
 cabal-version:      1.18
 name:               crypton
-version:            1.0.2
+version:            1.0.3
 license:            BSD3
 license-file:       LICENSE
 copyright:          Vincent Hanquez <vincent@snarc.org>
