') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); elliptic-curve: ensure PublicKey is not the identity point by tarcieri · Pull Request #404 · RustCrypto/traits · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions elliptic-curve/src/ecdh.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,7 +31,7 @@ use crate::{
use core::{fmt::Debug, ops::Add};
use ff::PrimeField;
use generic_array::ArrayLength;
use group::{Curve as _, Group};
use group::Curve as _;
use rand_core::{CryptoRng, RngCore};
use zeroize::Zeroize;

Expand DownExpand Up@@ -69,7 +69,7 @@ where
///
/// The `compress` flag enables point compression.
pub fn public_key(&self) -> PublicKey<C> {
PublicKey::from_affine((C::ProjectivePoint::generator() * self.scalar.as_ref()).to_affine())
PublicKey::from_secret_scalar(&self.scalar)
}

/// Compute a Diffie-Hellman shared secret from an ephemeral secret and the
Expand Down
32 changes: 24 additions & 8 deletions elliptic-curve/src/public_key.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@

use crate::{
consts::U1,
scalar::NonZeroScalar,
sec1::{
EncodedPoint, FromEncodedPoint, ToEncodedPoint, UncompressedPointSize, UntaggedPointSize,
},
Expand All@@ -15,6 +16,7 @@ use core::{
};
use ff::PrimeField;
use generic_array::ArrayLength;
use group::{Curve as _, Group};

#[cfg(feature = "pkcs8")]
use crate::{AlgorithmParameters, ALGORITHM_OID};
Expand All@@ -26,8 +28,8 @@ use core::str::FromStr;

/// Elliptic curve public keys.
///
/// These are a thin wrapper around [`AffinePoint`] which simplifies
/// encoding/decoding.
/// This is a wrapper type for [`AffinePoint`] which ensures an inner
/// non-identity point and provides a common place to handle encoding/decoding.
///
/// # Parsing "SPKI" Keys
///
Expand DownExpand Up@@ -67,10 +69,24 @@ where
FieldBytes<C>: From<Scalar<C>> + for<'r> From<&'r Scalar<C>>,
Scalar<C>: PrimeField<Repr = FieldBytes<C>>,
AffinePoint<C>: Copy + Clone + Debug,
ProjectivePoint<C>: From<AffinePoint<C>>,
{
/// Convert an [`AffinePoint`] into a [`PublicKey`]
pub fn from_affine(point: AffinePoint<C>) -> Self {
Self { point }
pub fn from_affine(point: AffinePoint<C>) -> Result<Self, Error> {
if ProjectivePoint::<C>::from(point).is_identity().into() {
Err(Error)
} else {
Ok(Self { point })
}
}

/// Compute a [`PublicKey`] from a secret [`NonZeroScalar`] value
/// (i.e. a secret key represented as a raw scalar value)
pub fn from_secret_scalar(scalar: &NonZeroScalar<C>) -> Self {
// `NonZeroScalar` ensures the resulting point is not the identity
Self {
point: (C::ProjectivePoint::generator() * scalar).to_affine(),
}
}

/// Decode [`PublicKey`] (compressed or uncompressed) from the
Expand DownExpand Up@@ -98,10 +114,7 @@ where
}

/// Convert this [`PublicKey`] to a [`ProjectivePoint`] for the given curve
pub fn to_projective(&self) -> ProjectivePoint<C>
where
ProjectivePoint<C>: From<AffinePoint<C>>,
{
pub fn to_projective(&self) -> ProjectivePoint<C> {
self.point.clone().into()
}
}
Expand All@@ -112,6 +125,7 @@ where
FieldBytes<C>: From<Scalar<C>> + for<'r> From<&'r Scalar<C>>,
Scalar<C>: PrimeField<Repr = FieldBytes<C>>,
AffinePoint<C>: Copy + Clone + Debug,
ProjectivePoint<C>: From<AffinePoint<C>>,
{
fn as_ref(&self) -> &AffinePoint<C> {
self.as_affine()
Expand DownExpand Up@@ -262,6 +276,7 @@ where
FieldBytes<C>: From<Scalar<C>> + for<'r> From<&'r Scalar<C>>,
Scalar<C>: PrimeField<Repr = FieldBytes<C>>,
AffinePoint<C>: Copy + Clone + Debug,
ProjectivePoint<C>: From<AffinePoint<C>>,
UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
UncompressedPointSize<C>: ArrayLength<u8>,
{
Expand DownExpand Up@@ -291,6 +306,7 @@ where
FieldBytes<C>: From<Scalar<C>> + for<'r> From<&'r Scalar<C>>,
Scalar<C>: PrimeField<Repr = FieldBytes<C>>,
AffinePoint<C>: Copy + Clone + Debug,
ProjectivePoint<C>: From<AffinePoint<C>>,
UntaggedPointSize<C>: Add<U1> + ArrayLength<u8>,
UncompressedPointSize<C>: ArrayLength<u8>,
{
Expand Down
6 changes: 3 additions & 3 deletions elliptic-curve/src/secret_key.rs
Original file line numberDiff line numberDiff line change
Expand Up@@ -18,11 +18,10 @@ use zeroize::Zeroize;
#[cfg(feature = "arithmetic")]
use crate::{
ff::PrimeField,
group::{Curve as _, Group},
public_key::PublicKey,
rand_core::{CryptoRng, RngCore},
scalar::{NonZeroScalar, Scalar},
weierstrass, AffinePoint, ProjectiveArithmetic,
weierstrass, AffinePoint, ProjectiveArithmetic, ProjectivePoint,
};

#[cfg(feature = "pkcs8")]
Expand DownExpand Up@@ -133,8 +132,9 @@ where
FieldBytes<C>: From<Scalar<C>> + for<'a> From<&'a Scalar<C>>,
Scalar<C>: PrimeField<Repr = FieldBytes<C>> + Zeroize,
AffinePoint<C>: Copy + Clone + Debug + Default,
ProjectivePoint<C>: From<AffinePoint<C>>,
{
PublicKey::from_affine((C::ProjectivePoint::generator() * self.secret_scalar()).to_affine())
PublicKey::from_secret_scalar(self.secret_scalar())
}
}

Expand Down